问题
I have been playing around with std::vector to understand when objects are constructed, destructed, copy constructed and move constructed. To so do, I have written the following program
#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;
}
When a is resized, reallocation happens. My guess would have been that the object a[0] is moved constructed to the new a[0]. But, with libc++ and libstdc++, it seems that the copy constructor is called and not the move constructor. Is there any reason for such a behaviour?
回答1:
I just found the answer to the question. The move constructor has to be declared noexcept to do so. When such a change has been done
Test(Test&& x) noexcept {
std::cout << "Move Constructor called for " << this << std::endl;
}
the move constructor is called.
回答2:
Just as @InsideLoop's answer said, the move constructor has to be declared "noexcept" to be called.
It is because in the vector::resize() function call stack, we can find move_if_noexcept() is called in function __construct_backward().(see [your library path]/include/c++/v1/memory line:1531)
construct(__a, _VSTD::__to_raw_pointer(__end2-1), _VSTD::move_if_noexcept(*--__end1));
According to the C++11 standard, we know that move constructor is used for temporary right value in normal. So the move constructor throwing exception is such a dangerous thing, and we can declare "noexcept" for the move constructor to avoid it.
Using move_if_noexcept(), although it loss in performance, but can make the process safe. And the function will activate the move constructor when move constructor is declared "noexcept".
(Sorry for my poor English.)
来源:https://stackoverflow.com/questions/28166001/resize-on-stdvector-does-not-call-move-constructor