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

Why Copy constructor is called along with Move Constructor?

本文关键字:构造函数 调用 一起 复制 为什么 移动      更新时间:2023-10-16

这个问题看起来很奇怪,但我已经检查了多个编译器。在我的代码中,我有一个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

谢谢

原因已经在评论中回答了。 我将尝试说明正在发生的事情。

步骤:

vector<A> v1;

  1. 矢量的分配。它在内部为一个元素保留空间。

v1.push_back(A(100));

  1. 构造和向量内A(100)的移动。

v1.push_back(move(a2));

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

记忆:

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))避免移动。