为何使用右值引用时unique_ptr的所有权未发生转移?
为什么右值引用参数的
std::unique_ptr未发生所有权转移? 要搞清楚这个问题,核心是理解std::unique_ptr的所有权转移逻辑,以及两种函数参数的本质区别:
1. 所有权转移的本质
std::unique_ptr的所有权转移,必须通过移动构造或移动赋值来完成——只有当你用一个右值unique_ptr去初始化另一个unique_ptr,或者赋值给它时,才会触发移动操作,把所有权从原对象转移到新对象。
2. 值传递参数的情况(第一种foo)
当foo的参数是std::unique_ptr<Myc> other(值传递)时:
- 调用
foo(std::move(pm))时,std::move(pm)将pm转换为右值引用; - 为了初始化函数参数
other,编译器会调用unique_ptr的移动构造函数,把pm的所有权转移给other; foo函数执行完毕后,局部变量other被销毁,连带销毁它所指向的Myc对象,所以输出顺序是End foo→Myc Destructed→End main。
3. 右值引用参数的情况(第二种foo)
当foo的参数是std::unique_ptr<Myc> &&other(右值引用)时:
std::move(pm)产生的右值引用,只是被绑定到了参数other上——other本质是原pm的一个"绑定别名",并没有创建新的unique_ptr对象;- 因为没有触发移动构造或移动赋值,所有权仍然属于
pm; foo函数执行完毕后,other作为引用不会销毁任何对象,直到main函数结束时pm被销毁,才会触发Myc的析构,所以输出顺序是End foo→End main→Myc Destructed。
验证:手动触发所有权转移
如果在第二种foo函数内部手动触发移动,所有权就会转移:
void foo(std::unique_ptr<Myc> &&other) { std::unique_ptr<Myc> local = std::move(other); // 触发移动构造,转移所有权 std::cout << "End foo\n"; }
此时local会接管所有权,foo结束时local销毁,析构信息会在End foo之后打印,和第一种情况的输出顺序一致。
内容的提问来源于stack exchange,提问作者rdabra
相关产品推荐
相关产品推荐

