Sor*_*rer 10 c++ move vector rvalue-reference c++11
我在std :: vector上有一些奇怪的行为,添加了rvalues:
#include <iostream>
#include <vector>
class A {
public:
A():i_{5}{std::cout << "default" << std::endl;}
A(const A &data) { std::cout << "copied!" << std::endl; }
A(A &&data) { std::cout << "moved " << std::endl; }
int i_;
};
int main(int argc, char *argv[]) {
std::vector<A> datavec;
datavec.push_back(A{});
datavec.push_back(A{});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
default
moved
default
moved
copied!
Run Code Online (Sandbox Code Playgroud)
因此,矢量仍然创建A的副本,我做的越多 - 我得到的副本越多.但是,如果我用默认的A替换移动构造函数A(A && data)= default; 或用A删除复制构造函数(const A&data)= delete; 我得到了正确的结果,没有复制.如果我先调用足够大小的datavec.reserve,我也没有副本.我使用gcc版本5.4.0没有特定的参数
g++ -std=c++11 -o main ../main.cpp
Run Code Online (Sandbox Code Playgroud)
你有没有想过为什么矢量复制明显的右值?我希望这不是STL的一些错误
Vit*_*meo 14
将std::vector被复制在你的元素内部缓冲区重新分配.它选择复制而不是移动,因为您的移动构造函数未标记noexcept.标记它......
A(A &&) noexcept { std::cout << "moved " << std::endl; }
Run Code Online (Sandbox Code Playgroud)
......将解决问题.
告诉编译器您的移动构造函数不会抛出允许std::vector的实现在内部重新分配期间移动,从而实现C++标准所要求的异常保证.
或者,您可以std::vector::reserve提前装入容器以防止内部缓冲区的增长.