通过一个可移动的物体

时间:2013-09-22 14:16:51

标签: c++

在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) {}
};

哪一个是正确的?

2 个答案:

答案 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
}