gpt4 book ai didi

c++ - 为什么保留额外内存时 vector 中的对象没有 move ?

转载 作者:行者123 更新时间:2023-12-04 15:11:33 24 4
gpt4 key购买 nike

有如下代码:

#include <iostream>
#include <vector>

class Test {
public:
Test() {}
Test(int x) : x(x) {}

Test(const Test&) noexcept = delete;
Test& operator=(const Test&) noexcept = delete;

Test(Test&& r) noexcept { x = std::move(r.x); }
Test& operator=(Test&& r) noexcept {
std::cout << "move";
x = std::move(r.x);

return *this;
}

~Test() noexcept { std::cout << x; }

private:
int x;
};

int main() {
std::vector<Test> v;

v.reserve(5);
v.emplace_back(1);
v.emplace_back(2);
v.emplace_back(3);
v.emplace_back(4);
v.emplace_back(5);
v.reserve(10);
}

输出:

1234512345

我们看到了析构函数,但没有看到 move 赋值,因此我们可以得出结论,对象正在被复制而不是被 move 。这个问题已经在几个主题中讨论过,但没有一个具体的答案。

有一个使用 unique_ptrs 的解决方法:

#include <iostream>
#include <vector>
#include <memory>

class Test {
public:
Test() {}
Test(int x) : x(x) {}

Test(const Test&) noexcept = delete;
Test& operator=(const Test&) noexcept = delete;

Test(Test&& r) noexcept { x = std::move(r.x); }
Test& operator=(Test&& r) noexcept {
std::cout << "move";
x = std::move(r.x);

return *this;
}

~Test() noexcept { std::cout << x; }

private:
int x;
};

int main() {
std::vector<std::unique_ptr<Test>> v;

v.reserve(5);
v.emplace_back(std::make_unique<Test>(1));
v.emplace_back(std::make_unique<Test>(2));
v.emplace_back(std::make_unique<Test>(3));
v.emplace_back(std::make_unique<Test>(4));
v.emplace_back(std::make_unique<Test>(5));
v.reserve(10);
}

输出:

12345

所有代码在编译器 gcc 5.1 - 10.2 上测试

为什么在 vector 中分​​配内存而不是 move 时会发生对象复制?为什么第一个代码块中没有使用 move 语义,这种行为的原因是什么?

最佳答案

声明v.reserve(10);使您的 vector 重新分配其存储空间,以便它可以容纳至少 10 个元素。假设capacity小于 10,这是一个四步过程:

  1. 新存储已分配,足够了 capacity将至少为 10。

  2. 需要将先前存储中的元素 move 到新存储中。对于先前存储中的每个元素,将该元素的值 move 到新存储中的新实例中。

  3. 在释放旧存储之前,仍需要销毁移出的实例。这会导致它们的每个析构函数执行,打印 12345在你的情况下。请注意,每个移出的实例仍具有其旧值 x。 . move int等同于复制,原值不变。

  4. 现在释放了以前的存储空间。 vector 现在使用新存储,它包含等效元素但比以前的存储更大。

最后,在main的结尾你的 vector v必须被摧毁。这也会导致它的每个元素都被销毁,从而导致每个析构函数都被执行。这是第二组 12345打印出来。

std::unique_ptr你只看到一组数字 ( 12345 ) 因为 unique_ptr s 在两个存储之间 move ,而不是 Test秒。 std::unique_ptr<Test> 的新 move 构造实例取得指针的所有权,旧的移出实例不再拥有这些指针。当先前存储中的实例被销毁时,它们的析构函数什么都不做(因为它们不再拥有指针)。你只看到你的 Test 的破坏v 时的实例在 main 结束时被销毁.然后,std::unique_ptr被销毁的实例确实拥有指向Test的指针, 所以结果是 Test实例是 delete d.

编辑:请注意,您只检测了 move 赋值运算符。 std::vector在这种情况下将使用 move 构造函数,因此您不会看到 "move"即使 Test 的实例由 v move .

关于c++ - 为什么保留额外内存时 vector 中的对象没有 move ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65149793/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com