【问题标题】:C++11 vector makes copies on rvalue [duplicate]C ++ 11向量在右值上复制[重复]
【发布时间】:2017-08-31 06:57:12
【问题描述】:

我在 std::vector 添加右值时有一些奇怪的行为:

#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!

所以 vector 仍然会创建 A 的副本,我做的推动越多 - 我得到的副本就越多。 但是,如果我用默认的 A(A &&data) = default; 替换移动构造函数或用 A(const A &data) = delete; 删除复制构造函数,我会得到正确的结果没有复制的地方。如果我首先调用具有足够大小的 datavec.reserve,我也没有副本。 我使用没有特定参数的 gcc 版本 5.4.0

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

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

【问题讨论】:

  • 好问题,好答案,好重复的地方。

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


【解决方案1】:

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

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

...将解决问题。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-16
    • 2014-09-18
    • 2013-08-07
    • 2012-12-10
    • 2014-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多