copy vs std :: move for thets

时间:2015-01-11 15:41:08

标签: c++ c++11 move-semantics

  • 该示例中默认副本和std :: move之间有什么区别?
  • move之后,对象是否存在新旧对象之间的依赖关系?
int main () {

    int a = 100;
    std::cout<<&a<<std::endl;

    auto a_copy = a;                 // deduced as int
    std::cout<<&a_copy<<std::endl;

    auto a_move = std::move(a);      // deduced as int
    std::cout<<&a_move<<std::endl;

};

输出:

0x7fffffffe094
0x7fffffffe098
0x7fffffffe09c

4 个答案:

答案 0 :(得分:25)

这个示例中,没有区别。我们最终得到3 int s,其值为100.但不同类型的确存在差异。例如,让我们考虑类似vector<int>

的内容
std::vector<int> a = {1, 2, 3, 4, 5}; // a has size 5
auto a_copy = a;                      // copy a. now we have two vectors of size 5
auto a_move = std::move(a);           // *move* a into a_move

最后一个变量a_move取得a内部指针的所有权。所以我们最终得到的是a_move是一个大小为5的向量,但a现在是空的。 movecopy更有效(想象一下,如果它是一个1000字符串的向量 - a_copy将涉及分配一个1000字符串的缓冲区并复制1000个字符串,但{a_move 1}}只分配几个指针)。

对于其他一些类型,可能无效:

std::unique_ptr<int> a{new int 42};
auto a_copy = a;            // error
auto a_move = std::move(a); // OK, now a_move owns 42, but a points to nothing

对于许多类型,但没有区别:

std::array<int, 100> a;
auto a_copy = a;            // copy 100 ints
auto a_move = std::move(a); // also copy 100 ints, no special move ctor

更一般地说:

T a;
auto a_copy = a;            // calls T(const T& ), the copy constructor
auto a_move = std::move(a); // calls T(T&& ), the move constructor

答案 1 :(得分:11)

使用std::move只是将左值更改为xvalue,因此它适用于移动构造函数和移动赋值运算符。对于内置类型,这些不存在,因此在此示例中使用move没有区别。

答案 2 :(得分:6)

  

该示例中的默认副本和std :: move之间有什么区别?

没有区别。复制某些内容可以满足移动的要求,对于内置类型,移动可以作为副本实现。

  

移动对象后,新旧之间存在依赖性

不,没有依赖关系。两个变量都是独立的。

答案 3 :(得分:3)

为了扩展另一张海报的答案,移动即复制范例也适用于由POD类型组成的所有数据结构(或由POD类型组成的其他类型组成),如本例如:

struct Foo
{
    int values[100];
    bool flagA;
    bool flagB;
};

struct Bar
{
    Foo foo1;
    Foo foo2;
};

int main()
{
    Foo f;
    Foo fCopy = std::move(f);
    Bar b;
    Bar bCopy = std::move(b);
    return 0;
}

FooBar的情况下,没有有意义的方法将数据从一个移动到另一个,因为它们最终都是POD类型的聚合 - 它们的数据都不是间接拥有的(点数)或引用其他记忆)。因此,在这些情况下,移动是作为副本实现的,而原始文件(fb)在std::move()行上的分配后保持不变。

移动语义只能通过动态分配的内存或唯一资源实现。