【问题标题】:Can I move the object pointed by a unique_ptr into a vector without copying?我可以在不复制的情况下将 unique_ptr 指向的对象移动到向量中吗?
【发布时间】:2022-11-22 10:40:10
【问题描述】:

假设我有一个 Foo 类的 unique_ptr 和一个 Foo 的向量:

class Foo { ... };

std::unique_ptr<Foo> fooPtr = std::make_unique<Foo>();

std::vector<Foo> fooVector;

现在,如果我要这样做:

fooVector.push_back(*fooPtr);

如果我没记错的话,这应该在向量中创建 Foo 实例的副本; “真实的”/原始的 Foo 仍然在内存中的某个地方被 fooPtr 指向。

我想做的是移动fooPtr 指向的内容,无需将任何内容复制到向量中(我不再需要指针),此编译:

fooVector.push_back(std::move(*fooPtr));

但我不确定它是否完全符合我的要求,或者它是否“安全”,因为在这个操作之后我仍然有 fooPtr。

我想拥有一个 unique_ptr 的向量然后移动 unique_ptr ownsership 会更容易,但我需要它像这样。

【问题讨论】:

  • 移动并不神奇。搬家是浅的复制(如果需要加上取消原件)。如果您的Foo 很深(拥有指向内部对象的指针),那么移动(== 浅层复制)它比普通(== 深)复制便宜。如果不是,那就不是。

标签: c++ c++11 move unique-ptr


【解决方案1】:

std::unique_ptr&lt;Foo&gt; 管理两个密切相关的事物的生命周期。

它管理的生命周期贮存Foo 存在于该存储中,Foo 对象存在于该存储中。

std::vector&lt;Foo&gt; 管理Foos 缓冲区的存储和其中Foos 的生命周期。

unique_ptr 管理的存储空间足够单个 Foovector 管理的存储是连续存储多个Foo 的缓冲区。您不能神奇地移动存储空间;这就像移动街道地址一样。您可以搬家,但不能搬家。

没有一个操作既可以将 Foo 移出 unique_ptr 又可以销毁该存储。

fooVector.push_back(std::move(*fooPtr));
fooPtr = nullptr;

第一行会将fooPtr中的Foo移动到std::vector中(可能导致重新分配和一堆Foo移动)。

第二行清除unique_ptrfooPtr,丢弃存储并删除(移出的)对象。

在此操作之前存储指向 *fooPtr 的指针的任何对象现在都将有一个悬挂指针,但只有一个(活动的)Foo 对象。

有些编程语言不允许对象存在于由编程语言框架以外的任何东西管理的存储中。在这些语言中,对象和对对象的引用大多是可互换的概念,通常使用 gc 来在引用存在时保留对象。

在 C++ 中,Foo 实际上是存储在那里的 Foo,而不是对语言框架管理的存储中的 Foo 的引用。 vector&lt;Foo&gt; 是一个缓冲区std::vector代码管理连续存储的实际Foos,而不是其他语言倾向于拥有的引用Foo的缓冲区。

这种差异使 C++ 比基于 gc 的语言具有大约 2 倍的性能优势,因为程序员可以使数据成为本地数据并管理数据的生命周期比其他语言容易得多。它给程序员带来了额外的负担,因为它还迫使程序员管理对象和存储生命周期。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-13
    • 2014-07-21
    • 2016-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    相关资源
    最近更新 更多