C++ 在 std::move() 之后 unique_ptr 会发生什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36071220/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:34:42  来源:igfitidea点击:

What happens to unique_ptr after std::move()?

c++unique-ptr

提问by user3496846

This code is what I want to do:

这段代码是我想要做的:

Tony& Movie::addTony()
{
    Tony *newTony = new Tony;
    std::unique_ptr<Tony> tony(newTony);
    attachActor(std::move(tony));
    return *newTony;
}

I am wondering if I could do this instead:

我想知道我是否可以这样做:

Tony& Movie::addTony()
{
    std::unique_ptr<Tony> tony(new Tony);
    attachActor(std::move(tony));
    return *tony.get();
}

But will *tony.get()be the same pointer or null? I know I could verify, but what is the standard thing for it to do?

但是会*tony.get()是同一个指针还是null?我知道我可以验证,但它的标准做法是什么?

回答by Benjamin Lindley

No, you cannot do that instead. Moving the unique_ptrnulls it. If it didn't, then it would not be unique. I am of course assuming that attachActordoesn't do something silly like this:

不,你不能这样做。移动unique_ptr空值它。如果没有,那么它就不是唯一的。我当然假设这attachActor不会做这样愚蠢的事情:

attachActor(std::unique_ptr<Tony>&&) {
    // take the unique_ptr by r-value reference,
    // and then don't move from it, leaving the
    // original intact
}

Section 20.8.1 paragraph 4.

第 20.8.1 节第 4 段。

Additionally, u (the unique_ptr object) can, upon request, transfer ownership to another unique pointer u2. Upon completion of such a transfer, the following postconditions hold:
   -- u2.p is equal to the pre-transfer u.p,
   -- u.p is equal to nullptr, and
   -- if the pre-transfer u.d maintained state, such state has been transferred to u2.d.

此外,u(unique_ptr 对象)可以根据请求将所有权转移到另一个唯一指针 u2。完成这样的传输后,以下后置条件成立:
   -- u2.p 等于传输前 up,
   -- up 等于 nullptr,并且
   -- 如果传输前 ud 保持状态,则该状态已转移到u2.d。

回答by 5gon12eder

The standard says (§ 20.8.1.2.1 ? 16, emphasis added) that the move constructor of std::unique_ptr

标准说(§ 20.8.1.2.1 ? 16,强调添加)移动构造函数 std::unique_ptr

unique_ptr(unique_ptr&& u) noexcept;

Constructs a unique_ptrby transferring ownershipfrom uto *this.

unique_ptr(unique_ptr&& u) noexcept;

unique_ptr通过将所有权转移u来构造*this

Therefore, after you move-construct the temporary object that gets passed as argument to attachActorform your tony, tonyno longer owns the object and hence tony.get() == nullptr. (This is one of the few cases where the standard library actually makes assertions about the state of a moved-away-from object.)

因此,后移动,构建被作为参数传递给临时对象attachActor形成的tonytony不再拥有的对象,因此tony.get() == nullptr。(这是标准库实际上对远离对象的状态做出断言的少数情况之一。)

However, the desire to return the reference can be fulfilled without resorting to naked newand raw pointers.

但是,无需诉诸裸new指针和原始指针即可满足返回引用的愿望。

Tony&
Movie::addTony()
{
  auto tony = std::make_unique<Tony>();
  auto p = tony.get();
  attachActor(std::move(tony));
  return *p;
}

This code assumes that attachActorwill not drop its argument on the floor. Otherwise, the pointer pwould dangle after attachActorhas returned. If this cannot be relied upon, you'll have to re-design your interface and use shared pointers instead.

此代码假定attachActor不会将其参数放在地板上。否则,指针p会在attachActorhas returned之后悬空。如果不能依赖,则必须重新设计界面并改用共享指针。

std::shared_ptr<Tony>
Movie::addTony()
{
  auto tony = std::make_shared<Tony>();
  attachActor(tony);
  return tony;
}