为什么复制构造函数与Move Constructor一起被调用?

时间:2017-12-26 17:10:21

标签: c++ c++11 c++14 c++17

这个问题似乎很奇怪,但我已经检查过多个编译器。在我的代码中,我有一个Move Constructor和一个copy constructor

class A {
    int val;
public:
    A(int var) : val(var)  {
    }
    A( A && a1) {
        cout<<"M Value -> "<<a1.val<<endl;
        cout<<"Move Cons..."<<endl;
     }
    A(const A & a1) {
        cout<<"Copy Cons.."<<endl;
        cout<<"Value -> "<<a1.val<<endl;
    }
};

如果我将main函数写为

int main()
{
    vector<A> v1;
    A a2(200);
    v1.push_back(move(a2));              
}

输出

M Value -> 200
Move Cons...

这是预期的,但如果我将main功能更改为

int main()
{
    vector<A> v1;
    A a2(200);
    v1.push_back(A(100));
    v1.push_back(move(a2));

}

我得到以下输出

M Value -> 100
Move Cons...
M Value -> 200
Move Cons...
Copy Cons..   // unexpected
Value -> 0    // unexpected

任何人都可以帮助我了解这个copy constructor被调用的位置和方式..也是值0

由于

1 个答案:

答案 0 :(得分:1)

评论中已经回答了原因。 我将尝试说明发生了什么。

步骤:

vector<A> v1;

  1. 矢量的分配。它内部保留了一个元素的空间。
  2. v1.push_back(A(100));

    1. 构建并在向量中移动A(100)
    2. v1.push_back(move(a2));

      1. 由于您尝试插入一个超过实际最大大小的新元素,因此将其重新分配到新的内存空间。请记住,std::vector将其内容保留在连续的内存中。
      2. a2移到v1
      3. 将原始v1的其余元素(在本例中仅为第一个)复制到新v1
      4. 内存:

        1) ## v1[undef ] #########################
        2) ## v1[A(100)] #########################
        3) ##   [A(100)] ### v1[undef,  undef ] ##
        4) ##   [A(100)] ### v1[undef,  A(200)] ##
        5) ##   [A(100)] ### v1[A(100), A(200)] ##
        

        附加说明:

        与值0相关,这是因为这些复制和移动构造函数实际上什么都不做,val值仍未定义。 使用适当的构造函数,此日志应为100。

        如果将移动构造函数标记为noexcept,则它将在重新分配过程中使用,而不是复制过程。

        您可以使用v1.emplace_back(100)代替v1.push_back(A(100))避免移动。