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

use*_*846 28 c++ unique-ptr

这段代码是我想要做的:

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

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

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

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

Ben*_*ley 29

不,你不能这样做.移动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
}
Run Code Online (Sandbox Code Playgroud)

第20.8.1节第4节.

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


5go*_*der 11

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

unique_ptr(unique_ptr&& u) noexcept;
Run Code Online (Sandbox Code Playgroud)

构造一个unique_ptr通过转移所有权,从u*this.

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

然而,可以在不诉诸裸露new和原始指针的情况下实现返回参考的愿望.

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

此代码假定attachActor不会将其参数丢弃在地板上.否则,指针p后会吊着attachActor已经return编.如果无法依赖,则必须重新设计界面并使用共享指针.

std::shared_ptr<Tony>
Movie::addTony()
{
  auto tony = std::make_shared<Tony>();
  attachActor(tony);
  return tony;
}
Run Code Online (Sandbox Code Playgroud)

  • 所有权转移并不意味着“u”不拥有任何东西,只是它不再拥有它之前拥有的对象。如果这是唯一的要求,则只需在“u”和“*this”之间**交换**对象所有权即可发生转移(这是其他一些移动构造函数为防止任何分配和释放而执行的操作)。但正如 Benjamin Lindley 指出的那样,除了文本上的“转让所有权”之外,对 std::unique_ptr 还有其他要求。 (2认同)