unique_ptr<T> 和 unique_ptr<T>&& 之间的区别 [重复]

Posted

技术标签:

【中文标题】unique_ptr<T> 和 unique_ptr<T>&& 之间的区别 [重复]【英文标题】:Difference between unique_ptr<T> and unique_ptr<T>&& [duplicate] 【发布时间】:2014-10-12 06:44:53 【问题描述】:

以下两个声明有什么区别?我什么时候应该更喜欢其中一个?

void f(unique_ptr<T> x);
void f(unique_ptr<T> &&x);

在我看来,这两种方法都意味着 f() 拥有指向对象的所有权,但我见过有人同时使用它们。我希望第一个是标准的,第二个被认为是不好的做法。

【问题讨论】:

第一个按值传递,因此不会用unique_ptr 编译,因为它是不可复制的。 @JonathanPotter - 你错了,如果你使用 move() 可以编译 A Brief Introduction to Rvalue References. f确实在第一种情况下取​​得所有权,而f可能在第二种情况下取​​得所有权。 你甚至不必使用 move,它只需要一个 r 值,例如函数返回值,或者直接调用构造函数。 【参考方案1】:

第二个版本,即采用引用的版本,效率稍高一些,因为没有为函数参数构造单独的对象。您会在通用库代码中发现这种样式,您不想将任何不必要的成本强加给用户。

第一个版本更容易阅读和记忆,并允许稍微更一般的建议“通过您想要拥有的价值传递事物”。该建议在您的情况下并不完全适用,但在其他情况下确实适用。考虑一个拥有字符串的类:

struct Foo

    std::string s_;
    Foo(std::string s) : s_(std::move(s)) 
;

通过按值传递构造函数参数,您现在可以从左值和右值字符串构造Foo,您可以决定是复制还是移动到std::string 的构造函数,而不用担心关于它自己。这降低了复杂性(假设您有五个这样的参数)。


作为一般建议的最后一句话,请记住,C++ 标准库认为绑定到右值引用的任何值都是无别名的,即由该引用引用,没有其他人引用.这是一个重要的“隐藏”语义假设。因此,即使右值引用是一个引用,并且您原则上可以使用它来引用某个共享状态,但也不要太过分,因为这会出乎意料和令人惊讶。

【讨论】:

+1 表示最后一个字(如果没有别的)。 一个切入点:“按值移动”很容易教。这是直截了当和明显的(你有一个价值,你最好摆脱它)。相比之下,许多新手在给出右值引用时会感到非常困惑,并且没有意识到他们still have to move - 尽管程序员有意请求移动语义,但忘记移动会默默地降低性能。 要注意的另一件事是,如果您传递左值(使用 clang),您会从编译器获得的错误消息类型:使用 by-value 参数,您会得到 call to implicitly-deleted copy constructor of 'std::unique_ptr&lt;T&gt;',而不是 by-右值参考版本no matching function for call to 'f'。 IMO 第一个更清晰。

以上是关于unique_ptr<T> 和 unique_ptr<T>&& 之间的区别 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

unique_ptr<T> 和 unique_ptr<T>&& 之间的区别 [重复]

在 std::vector<T> 和 std::vector<unique_ptr<T>> 上均匀迭代

为啥 unique_ptr<T> 不能从 T* 构造?

`unique_ptr< T const [] >` 是不是应该接受 `T*` 构造函数参数?

两个 unique_ptr<T> 的无锁交换

vector<unique_ptr<T> > 作为基类成员