简体   繁体   English

为什么不通过右值引用接受 std::unique_ptr?

[英]Why not to accept std::unique_ptr by rvalue reference?

Can somebody explain why everybody passes std::unique_ptr by value instead of by rvalue reference?有人可以解释为什么每个人都按值而不是右值引用传递std::unique_ptr吗?

From what I've observed, this required an additional move constructor to be invoked.根据我的观察,这需要调用一个额外的移动构造函数。

Here's an example of a class holding a "pointer".这是一个 class 持有“指针”的例子。 It takes 3 move-ctor calls to take it by value, versus 2 calls to take it by reference:它需要 3 次 move-ctor 调用才能按值获取它,而需要 2 次调用才能通过引用获取它:

#include <memory>
#include <iostream>

class pointer {
public:
    pointer()
    { std::cerr << "ctor" << std::endl; }
    
    pointer(const pointer&)
    { std::cerr << "copy-ctor" << std::endl; }
    
    pointer& operator=(const pointer&)
    { std::cerr << "copy-assignment" << std::endl; return *this; }
    
    pointer(pointer&&)
    { std::cerr << "move-ctor" << std::endl; }
    
    pointer& operator=(pointer&&)
    { std::cerr << "move-assignment" << std::endl; return *this; }
    
    ~pointer()
    { std::cerr << "dtor" << std::endl; }
};

class A {
public:
    // V1
    A(pointer _ptr) : ptr(std::move(_ptr)) {}
        
    // V2
    A(pointer&& _ptr) : ptr(std::move(_ptr)) {}

private:
    pointer ptr;
};

int main() {
    // Three calls to move-ctor versus two calls if pass by rvalue reference
    auto ptr = pointer();
    A a(std::move(ptr));

    // Two calls to move-ctor always
    A a(pointer{});
}

Passing a unique_ptr by reference, rvalue or otherwise, doesn't actual move anything, so you can't know by just looking at the function declaration if a move will happen.通过引用、右值或其他方式传递unique_ptr不会实际移动任何东西,因此仅查看 function 声明您无法知道是否会发生移动。

Passing a unique_ptr by value on the other hand guarantees that the passed in pointer will be moved from, so without even have to look at the documentation you know calling that function releases you from the pointers' ownership.另一方面,按值传递unique_ptr保证传入的指针将从中移出,因此甚至不必查看文档,您就知道调用 function 可以使您摆脱指针的所有权。

For the same reason people pass int instead of const int& .出于同样的原因,人们传递int而不是const int&

std::unique_ptr is just an RAII wrapper around a single pointer value, so moving it is just copying a single register width value, then zeroing the source. std::unique_ptr只是单个指针值的 RAII 包装器,因此移动它只是复制单个寄存器宽度值,然后将源清零。 That's so trivial there's no real benefit to avoiding the move.这太微不足道了,避免移动没有真正的好处。 After all, the cost to pass the reference (when not inlined) is the cost of passing a pointer too, so passing by reference can be less efficient (because if not inlined, it has to follow the reference to the real memory, then pull out the value from there; the top of the stack is likely in L1 cache, who knows if the place it's stored is?).毕竟,传递引用(未内联时)的成本也是传递指针的成本,因此通过引用传递可能效率较低(因为如果未内联,它必须遵循对真实 memory 的引用,然后拉从那里取出值;堆栈的顶部可能在 L1 缓存中,谁知道它存储的位置是不是?)。

In practice, much of this will be inlined with optimizations enabled, and both approaches would get the same result.在实践中,其中大部分将在启用优化的情况下进行内联,并且两种方法都会得到相同的结果。 Passing by value is a good default when there's no benefit to passing by reference, so why not do it that way?当按引用传递没有任何好处时,按值传递是一个很好的默认设置,那么为什么不这样做呢?

why everybody passes the std::unique_ptr by value instead of rvalue reference?为什么每个人都按值而不是右值引用传递 std::unique_ptr?

It may be more common, but it's not "everybody".它可能更常见,但不是“每个人”。

The drawback of std::unique_ptr&& parameter is that it doesn't explicitly communicate to the caller whether the pointer will be moved from or not. std::unique_ptr&&参数的缺点是它没有明确地与调用者沟通指针是否会被移动。 It might always move, or it might depend on some condition.它可能总是移动,或者可能取决于某些条件。 You would have to know the implementation or at least API documentation to know for sure.您必须知道实现或至少 API 文档才能确定。 The corresponding benefit of std::unique_ptr parameter is that it alone tells the reader of the declaration that the function will take ownership of the pointer. std::unique_ptr参数的相应好处是它单独告诉声明的读者 function 将获得指针的所有权。 For this reason, it may be a good choice to use std::unique_ptr parameter and probably part of the reason why it's more common.出于这个原因,使用std::unique_ptr参数可能是一个不错的选择,这可能是它更常见的部分原因。

The benefit of std::unique_ptr&& is avoiding the extra move. std::unique_ptr&&的好处是避免了额外的移动。 However, moving of a std::unique_ptr is a very fast operation.然而,移动std::unique_ptr是一个非常快速的操作。 It's insignificant compared for example to the memory allocation itself.例如,与 memory 分配本身相比,它是微不足道的。 In most cases, it simply doesn't matter.在大多数情况下,这根本无关紧要。

The difference between the two is fairly subtle.两者之间的区别相当微妙。 std::unique_ptr&& parameter may be considered in a case where you've measured the move to have significant cost. std::unique_ptr&&参数可能会在您测量到移动成本很高的情况下被考虑。 Which is not very common.这不是很常见。 Or in cases where your API may be used in cases where that cost could be significant.或者在您的 API 可能用于成本可能很高的情况下。 It's hard to prove that this won't ever happen if you're writing a public API, so it is a more likely argument to use.很难证明如果您正在编写一个 public API 就不会发生这种情况,因此更有可能使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么 std::unique_ptr 构造函数接受外部指针? - Why does the std::unique_ptr constructor accept an external pointer? 带有 std::unique_ptr 的 BST:在参数中使用右值引用有什么区别? - BST with std::unique_ptr: What's difference in using rvalue reference in parameters? 返回对 std::unique_ptr 的引用的原因 - Reasons to return reference to std::unique_ptr 传递unique_ptr右值引用结果编译错误 - Passing unique_ptr rvalue reference result compile error 有没有办法将一些 unique_ptr 的右值引用传递给线程池 - Is there a way to pas rvalue reference of some unique_ptr to thread pool 为什么没有operator &lt;&lt; for std :: unique_ptr? - Why is there no operator<< for std::unique_ptr? 为什么 rvalue unique_ptr 的 operator* 返回左值? - Why does operator* of rvalue unique_ptr return an lvalue? 当 unique_ptr 在向量中时,对 std::unique_ptr<> owned object 的引用/ptr 是否安全? - Is having a reference/ptr to std::unique_ptr<> owned object safe when the unique_ptr is in a vector? 为什么 std::unique_lock 改变 std::unique_ptr? - Why std::unique_lock changes std::unique_ptr? 为什么C2662错误不适用于对std :: unique_ptr <B>对象</b>的const引用<B>?</b> - Why the C2662 error doesn't apply to a const reference to a std::unique_ptr<B> object?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM