2

阅读 SO 中的答案,他通过了一个vectorwith 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) {}
};

哪一个是正确的?

4

2 回答 2

2

函数参数已经按值获取,因此已经制作了副本。本地对象p毫无疑问是你的,也是你的,所以你可以无条件地离开它。

按值取参数的美妙之处在于它适用于左值和右值:对于左值,您制作一个真正的副本,因为您无能为力,但对于右值,函数参数本身可以通过移动来构造,所以只有曾经发生过一次昂贵的建筑,而其他一切都被搬走了。

于 2013-09-22T14:22:26.180 回答
2

当您从左值构造对象时,它将被复制。当您从非const右值构造对象时,它可以被移动(是否移动取决于具有移动构造函数的类)。在构造函数的上下文中,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
}
于 2013-09-22T14:23:33.997 回答