传递可移动对象

Passing a movable object

本文关键字:对象 可移动      更新时间:2023-10-16

在SO中阅读答案时,他通过了movevector。我认为正确的方法是在不使用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) {}
};

哪一个是正确的?

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

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

当您从左值构造对象时,它将被复制。当您从非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
}