理解std::move和unique_ptr

3

我刚接触C++11,正在试图理解std::moveunique_ptr的含义,为此编写了以下代码,在其中使用两种不同的方式对unique_ptr进行std::move:

void unique_ptr_plain_move() {
  unique_ptr<int> intptr(new int(10));
  unique_ptr<int> intptr2;

  printf("*intptr = %d\n", *intptr);
  intptr2 = std::move(intptr);
  printf("*intptr2 = %d\n", *intptr2);
  // as expected, crash here as we have already moved intptr's ownership.
  printf("*intptr = %d\n", *intptr);
}

/////////////////////////////////////////////

void function_call_move(unique_ptr<int>&& intptr) {
  printf("[func] *intptr = %d\n", *intptr);
}

void unique_ptr_function_call_move() {
  unique_ptr<int> intptr(new int(10));

  printf("*intptr = %d\n", *intptr);
  function_call_move(std::move(intptr));
  // this does not crash, intptr still has the ownership of its pointed instance ....
  printf("*intptr = %d\n", *intptr);
}

在函数 unique_ptr_plain_move() 中,intptr2 在使用 std::move 后接手了 intptr 的所有权,因此我们不能再使用 intptr。然而,在函数调用中使用 std::move 时,比如在函数 unique_ptr_function_call_move() 中,intptr 仍然拥有其所指向的对象的所有权。当我们将一个 std::move(unique_ptr) 传递到一个函数中时,具体发生了什么呢?谢谢。

调用 std::move 并不会移动任何东西,它只是允许其他想要窃取对象内容的函数这样做。function_call_move 不是这样的一个函数。 - Igor Tandetnik
4
std::move可以从unique_ptr创建一个RValue引用。function_call_move接受一个RValue引用,但直到使用RValue引用赋值运算符或构造函数来窃取unique_ptr的信息之前,它才不会受到伤害。基本上,仅仅因为你能够抢劫并窃取其信息并不意味着你必须这样做。 - Dan
@Dan:非常感谢您的评论。所以是=操作进行所有权转移,而不是std::move,我在这部分是正确的吗? - keelar
1个回答

5
关键概念在于,std::move本身不会进行任何移动操作。你可以将其视为标记对象为可被移动的对象。 function_call_move 的签名如下:
void function_call_move( unique_ptr<int>&& ptr );

这意味着只能接收可移动的对象(即rvalues),并将其绑定到引用上。将rvalue关联到rvalue引用不会使原始对象的状态无效。

因此,除非function_call_move在内部实际上将ptr移动到另一个std::unique_ptr 中,否则对function_call_move(std::move(intptr));的调用不会使intptr无效,您的使用方式将是完全正确的。


1
非常抱歉我一开始没有为 function_call_move 提供签名,但是在我发现后我已经提供了。非常感谢您详细的回答! - keelar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接