我一直在使用std :: vector来理解何时构造,破坏,复制构造和移动构造的对象。为此,我写了以下程序
#include <iostream>
#include <vector>
class Test {
public:
Test() {
std::cout << "Constructor called for " << this << std::endl;
}
Test(const Test& x) {
std::cout << "Copy Constructor called for " << this << std::endl;
}
Test(Test&& x) {
std::cout << "Move Constructor called for " << this << std::endl;
}
~Test() {
std::cout << "Destructor called for " << this << std::endl;
}
};
int main() {
std::vector<Test> a( 1 );
a.resize(3);
return 0;
}
调整大小后,会重新分配。我的猜测是将对象a [0]移动构造为新的a [0]。但是,使用libc ++和libstdc ++,似乎调用了复制构造函数而不是移动构造函数。这种行为有什么理由吗?
答案 0 :(得分:13)
我刚刚找到了问题的答案。移动构造函数必须声明为noexcept才能这样做。当这样的改变已经完成时
Test(Test&& x) noexcept {
std::cout << "Move Constructor called for " << this << std::endl;
}
调用move构造函数。
答案 1 :(得分:3)
正如@ InsideLoop的回答所说,移动构造函数必须声明&#34; noexcept&#34;被召唤。
因为在vector :: resize()函数调用堆栈中,我们可以在函数 __ construct_backward()中找到 move_if_noexcept()。(参见[你的]库路径] / include / c ++ / v1 / memory line:1531)
construct(__a, _VSTD::__to_raw_pointer(__end2-1), _VSTD::move_if_noexcept(*--__end1));
根据C ++ 11标准,我们知道移动构造函数用于正常的临时右值。因此移动构造函数抛出异常是一件非常危险的事情,我们可以声明&#34; noexcept&#34;为移动构造函数避免它。
使用 move_if_noexcept(),虽然性能下降,但可以使过程安全。当声明移动构造函数时,该函数将激活移动构造函数&#34; noexcept&#34;。
(抱歉我的英语不好。)