C++ 为什么复制构造函数与移动构造函数一起调用?

C++ 为什么复制构造函数与移动构造函数一起调用?,c++,c++11,c++14,c++17,C++,C++11,C++14,C++17,这个问题看起来很奇怪,但我已经用多个编译器检查过了。在我的代码中,我有一个移动构造函数和一个复制构造函数作为 class A { int val; public: A(int var) : val(var) { } A( A && a1) { cout<<"M Value -> "<<a1.val<<endl; cout<<"Move Cons..."<&

这个问题看起来很奇怪,但我已经用多个编译器检查过了。在我的代码中,我有一个
移动构造函数
和一个
复制构造函数
作为

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;
    }
};
输出是

M Value -> 200
Move Cons...
这是预期的,但如果我将
main
函数更改为

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

}
有谁能帮助我理解调用此
复制构造函数的位置和方式吗。。值
0


谢谢

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

步骤:
向量v1

  • 向量的分配。它在内部为一个元素保留空间
  • v1.向后推(A(100))

  • 在向量内部构造和移动
    A(100)
  • v1.向后推(移动(a2))

  • 因为您试图插入一个新元素,超过了实际的最大大小,所以它被重新分配到一个新的内存空间。请记住,
    std::vector
    将其内容保存在连续内存中
  • a2
    移动到
    v1
  • 将原始
    v1
    的其余元素(在本例中仅为第一个)复制到新的
    v1
  • 内存: 补充说明: 与值0相关,这是因为这些复制和移动构造函数实际上什么都不做,并且
    val
    value仍然未定义。 使用适当的构造函数,此日志应为100

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


    您可以使用
    v1.将
    v1.向后放置(100)
    而不是
    v1.向后推(A(100))
    避免移动。

    Vector需要重新分配其存储以便增长,并将第一个元素复制到新存储。标记move构造函数
    noexcept
    ,那么一个好的实现将能够移动元素。至于值0-您的复制和移动构造函数实际上不复制任何内容,并保持
    this->val
    未初始化。当通过访问未初始化的对象进一步移动或复制此类对象时,程序会显示未定义的行为。在您的例子中,
    val
    中不可预测的值恰好是0。大多数(至少如果它们符合要求的话)标准库实现的
    std::vector
    只有在它们包含的元素满足要求时才会移动元素,因为
    vector
    需要实现强异常保证。如果他们不能移动,他们将退回复制。让你的移动构造函数
    noexcept
    。你也可以在推回之前保留存储,以避免在向量中重新分配:
    v1.reserve(2)
    .Daksh,我回答了你的问题。空向量可能没有为一个元素分配空间,但第一个调整大小是invisible@Caleth,你很可能是对的。由于vector Growth依赖于实现,并且我们没有使用显式的调整大小,所以还不清楚。因此,为了清晰起见,我尽量保持它的简单性。
    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
    
    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)] ##