在SO中阅读答案时,他通过了vector
move
。我认为正确的方法是在不使用move
的情况下简单地传递它:
class B
{
std::vector<T> data;
public:
B(std::vector<T> p) : data(std::move(p)) {}
^^^^^^^^^^^^
?
};
第二种方式是:
class B
{
std::vector<T> data;
public:
B(std::vector<T> p) : data(p) {}
};
哪一个是正确的?
答案 0 :(得分:2)
函数参数已经按值获取,因此已经创建了一个副本。本地对象p
毫无疑问是你自己和你自己的,所以你可以无条件地从它移动。
通过值获取参数的美妙之处在于它适用于左值和右值:对于左值,你可以制作一个真正的副本,因为你没有别的东西可以做,但对于右值,函数参数本身可以通过移动来构造,因此,只有一个昂贵的建筑发生,其他一切都被移动了。
答案 1 :(得分:2)
从左值构造对象时,它将被复制。当你从非const
rvalue构造一个对象时,它可以被移动(它是否会被移动取决于具有移动构造函数的类)。在构造函数的上下文中,p
显然是左值:它有一个名称。但是,它是一个局部变量,即将消失,即保存以从中移动:std::move(p)
使对象看起来好像是一个右值:在此上下文中,std::move()
价值是正确的方式。
请注意,如果返回对象,建议会有所不同:return
语句中返回的本地值会自动移出。使用std::move()
只会强化语句,但也会抑制完全删除副本/移动的可能性。在构造函数中,无法省略复制/移动,因为复制省略仅适用于临时对象或return
语句中的本地对象。
T f() {
T local;
return local; // good: elided, moved, or copied in this order of preference
}
T g() {
T local;
return std::move(local); // bad: can't be elided and will be moved or copied
}