【问题标题】:Guaranteeing move of large std::vector保证大 std::vector 的移动
【发布时间】:2017-03-08 07:37:07
【问题描述】:

我有一个大型数据集(数 GB)存储在一个不适合 QVector(最大 ~2gb)的文件中,该文件是写时复制的,不会受此影响。我像这样将向量加载到内存中:

std::vector<int> load()
{
    std::vector<int> vec;
    QFile file("filename");
    file.open(QIODevice::ReadOnly);
    QDataStream stream(&file);
    stream >> vec; //using my implementation of QDataStream &operator>>(QDataStream &stream, std::vector<int> &v)
    return vec;
}

并将其传递给这个:

class Data
{
public:
    Data(const std::vector<int> &data) :
        d(data)
    {
    }

private:
    std::vector<int> d;
};

这样:

Data data(load());

现在在load() 中创建了向量并用文件中的数据填充。然后它按值返回,但我认为编译器应该对其进行优化,而不是实际复制vec,而是将其移动到目的地。

目标是Data 的私有成员,但我怀疑构造函数中的初始化列表实际上可能会复制向量而不是移动它,因为它不知道(或者是吗?)它已收到一个 const 引用临时的。

有没有办法保证在这种场景下向量只会在构造后移动而不被复制?我怀疑使用std::movestd::forward 或更改Data::Data() 的签名来获取r 值参考?

【问题讨论】:

  • 既然您已经开始怀疑所有这些事情,那么是什么阻止您尝试它们?
  • @KerrekSB 事实上,我不会只使用一个编译器,我宁愿知道什么会起作用,而不是在所有因优化和诸如此类而绊倒的人身上尝试它。 .
  • 已经有一个更好的答案,但请注意,让 shared_ptr(或 unique_ptr,如果你可以管理)拥有向量将是避免复制的一种相当简单的方法。

标签: c++ qt c++11 vector


【解决方案1】:

您可以添加一个接受右值引用的构造函数,然后用它复制构造数据成员:

Data(std::vector<int>&& data) :
    d(std::move(data)) {}

Data(const std::vector<int>& data) // as before

有一个较短的版本,您可以将两个构造函数重载替换为一个,并按值获取参数。请注意,这依赖于右值参数的复制省略以避免任何额外的移动副本。它可能比两个重载解决方案做更多的工作,但与复制大向量* 的内容相比,工作量很小。它也可能需要额外的挠头,尽管它已经变得有点惯用了:

Data(std::vector<int> data) :
    d(std::move(data)) {}

* 请参阅 this related post,尤其是 Howard Hinnant 的回答。

【讨论】:

  • 请注意,执行第一个解决方案,然后消除 const&amp; 构造函数,防止用户不小心将向量复制到 Data 中——他们必须 将其移入。如果他们想复制,则必须创建一个临时并将其显式移入Data。这可能是值得的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-02
  • 2018-04-01
  • 2021-12-12
  • 2012-06-21
  • 1970-01-01
  • 1970-01-01
  • 2012-12-13
相关资源
最近更新 更多