【发布时间】:2017-12-26 17:10:21
【问题描述】:
这个问题看起来很奇怪,但我已经检查过多个编译器。在我的代码中,我有一个 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 需要重新分配其存储空间才能增长,并将第一个元素复制到新存储空间。标记移动构造函数
noexcept,然后一个好的实现将能够移动元素。 -
至于值 0 - 你的复制和移动构造函数实际上并没有复制任何东西,并且保持
this->val未初始化。当通过访问未初始化的对象进一步移动或复制此类对象时,您的程序会表现出未定义的行为。在您的情况下,val中不可预测的值恰好是 0。 -
std::vector的大多数(至少如果它们符合)标准库实现只会在它们包含的元素满足 std::move_if_noexcept 时移动元素,因为vector需要实现强异常保证。如果他们不能移动,他们将退回到复制。让你的移动构造函数noexcept. -
您还可以在推回之前保留存储以避免向量中的重新分配:
v1.reserve(2);。 -
Daksh,我回答了你的问题。