唯一指针:左值引用与右值引用函数调用
Unique Pointers: LValue Reference vs RValue Reference function calls
我开始使用 c++ std::unique_ptr
s 并且偶然发现了以下问题:
我想将我的唯一指针的引用传递给一个函数,并为该函数中的指针分配一个新值。直觉上,我认为该函数需要采用 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)
之间有什么区别,或者更确切地说,我应该为我的用例使用哪一个。所以也许有人可以解释一下每个函数的作用以及我应该使用哪个。
是的,他们做同样的事情。从您的意图来看,即按引用传递并在函数中修改它,按左值引用传递会更好。它使您的意图更加清晰(如@bitmask所建议的);该函数需要一个左值并会在函数内部对其进行修改。对于按右值引用传递,您需要使用 std::move
将左值传递给函数,并且它允许像临时值一样传递右值,这似乎毫无意义。例如
// meaningless; the temporary `std::unique_ptr` would be destroyed immediately
reseat_RValue(std::make_unique<Widget>(1998));
实际上 std::unique_ptr::reset 在带有左值引用的函数中为您做同样的事情 - 它更简单。 IMO,右值语义最适合大对象,而不是指针。但是,是的,unique_ptr 使用它来实现唯一的指针计数。
我开始使用 c++ std::unique_ptr
s 并且偶然发现了以下问题:
我想将我的唯一指针的引用传递给一个函数,并为该函数中的指针分配一个新值。直觉上,我认为该函数需要采用 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)
之间有什么区别,或者更确切地说,我应该为我的用例使用哪一个。所以也许有人可以解释一下每个函数的作用以及我应该使用哪个。
是的,他们做同样的事情。从您的意图来看,即按引用传递并在函数中修改它,按左值引用传递会更好。它使您的意图更加清晰(如@bitmask所建议的);该函数需要一个左值并会在函数内部对其进行修改。对于按右值引用传递,您需要使用 std::move
将左值传递给函数,并且它允许像临时值一样传递右值,这似乎毫无意义。例如
// meaningless; the temporary `std::unique_ptr` would be destroyed immediately
reseat_RValue(std::make_unique<Widget>(1998));
实际上 std::unique_ptr::reset 在带有左值引用的函数中为您做同样的事情 - 它更简单。 IMO,右值语义最适合大对象,而不是指针。但是,是的,unique_ptr 使用它来实现唯一的指针计数。