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)] ##