唯一指针:左值引用与右值引用函数调用

Posted

技术标签:

【中文标题】唯一指针:左值引用与右值引用函数调用【英文标题】:Unique Pointers: LValue Reference vs RValue Reference function calls 【发布时间】:2020-04-07 06:44:15 【问题描述】:

我开始使用 c++ std::unique_ptrs 并且偶然发现了以下问题:

我想将我的唯一指针的引用传递给一个函数,并为这个函数中的指针分配一个新值。直观地说,我认为该函数需要采用lvalue 引用才能修改指针。但是,在下面的代码示例中,两个选项(lvalue 参考和rvalue 参考 + std::move)做同样的事情(我想)。

#include <memory>
#include <utility>

struct Widget 
    Widget(int) 
;

void reseat_RValue(std::unique_ptr<Widget>&& uniqPtr) 
    auto tempUniqPtr = std::make_unique<Widget>(2003);
    uniqPtr = std::move(tempUniqPtr);


void reseat_LValue(std::unique_ptr<Widget>& uniqPtr) 
    auto tempUniqPtr = std::make_unique<Widget>(2010);
    uniqPtr = std::move(tempUniqPtr);


int main() 
    auto uniqPtr = std::make_unique<Widget>(1998);

    reseat_RValue(std::move(uniqPtr)); // (1)

    reseat_LValue(uniqPtr); // (2)   

我真的不明白,(1)(2) 之间有什么区别,或者更确切地说,我应该将哪一个用于我的用例。因此,也许有人可以解释每个函数发生了什么以及我应该使用哪个函数。

【问题讨论】:

【参考方案1】:

是的,他们做同样的事情。根据您的意图,即通过引用传递并在函数中修改它,通过左值引用传递会更好。它使您的意图更加清晰(如@bitmask 建议的那样);该函数需要一个左值,并会在函数内部对其进行修改。对于按右值引用传递,您需要使用std::move 将左值传递给函数,并且它允许像临时变量一样传递右值,这似乎毫无意义。例如

// meaningless; the temporary `std::unique_ptr` would be destroyed immediately
reseat_RValue(std::make_unique<Widget>(1998)); 

【讨论】:

加一个左值可以更好地在这里传达意图。【参考方案2】:

实际上 std::unique_ptr::reset 在具有左值引用的函数中为您做同样的事情 - 它更简单。 IMO,右值语义最适合大对象,而不是指针。但是是的,unique_ptr 使用它来实现唯一的指针计数。

【讨论】:

以上是关于唯一指针:左值引用与右值引用函数调用的主要内容,如果未能解决你的问题,请参考以下文章

左值引用与右值引用

左值引用与右值引用

左值引用与右值引用

左值引用与右值引用

左值引用与右值引用

右值引用,移动语义,完美转发