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

时间:2017-04-05 15:02:17

标签: c++ c++11 vector move rvalue-reference

我在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;
}

输出是:

default
moved 
default
moved 
copied!

因此,矢量仍会创建A的副本,我所做的推动越多 - 我获得的副本就越多。 但是,如果我用默认值 A(A&amp;&amp; data)=默认值; 替换移动构造函数,或者用 A(const A&amp; data)= delete删除复制构造函数我得到了正确的结果,没有制作副本。如果我先调用足够大小的datavec.reserve,我也没有副本。 我使用gcc版本5.4.0没有特定参数

g++ -std=c++11 -o main ../main.cpp

你有没有想过为什么矢量会复制明显的右值?我希望这不是STL的一些错误

1 个答案:

答案 0 :(得分:13)

{em}内部缓冲区重新分配期间std::vector正在复制元素。它选择复制而不是移动,因为您的移动构造函数未标记为noexcept。标记它......

A(A &&) noexcept {      std::cout << "moved " << std::endl; }

...将解决问题。

告诉编译器你的移动构造函数不会抛出允许std::vector的实现在内部重新分配期间移动,实现C ++所要求的异常保证标准。

或者,您可以提前std::vector::reserve您的容器,以防止内部缓冲区的增长。