在std :: vector上调整大小不会调用移动构造函数

时间:2015-01-27 08:23:31

标签: c++ c++11 vector move

我一直在使用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 ++,似乎调用了复制构造函数而不是移动构造函数。这种行为有什么理由吗?

2 个答案:

答案 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;。

(抱歉我的英语不好。)