C++ 11向量在rvalue上进行复制

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提前装入容器以防止内部缓冲区的增长.