【问题标题】:Using std::move() vs. assign in constructor member initializer list在构造函数成员初始值设定项列表中使用 std::move() 与分配
【发布时间】:2020-03-01 09:26:13
【问题描述】:

在参数化构造函数(带有初始化列表)中使用 std::move() 代替常规成员初始化,即赋值有什么好处?

例如,

#include <iostream>
#include <vector>

template <typename V>
class myVec{
    private:
        std::vector< std::vector<V> > vec;

    public:
        myVec1(const std::vector< std::vector<V> > &myArr):vec(myArr) {};
        myVec2(const std::vector< std::vector<V> > &myArr):vec(std::move(myArr)) {};
        };

使用 myVec1 而不是另一个可以获得多少优势(内存、性能等)?

【问题讨论】:

  • 当参数按值(或右值引用)传递时,您通常会看到这一点。

标签: c++ oop constructor initialization move-semantics


【解决方案1】:

在这种情况下没有性能差异。

std::move(myArr) 将生成对 myArr 的 const 右值引用。现在,由于 myArr 不可修改,因此将 this 绑定到右值引用是无效的,但它可以绑定到 const 左值引用。因此vec(std::move(myArr)) 最终将调用vector 的复制构造函数。

你想要的是:

myVec(const std::vector< std::vector<V> > &myArr):vec(myArr) {}; // 1
myVec(std::vector< std::vector<V> > &&myArr):vec(std::move(myArr)) {}; // 2

现在回到你原来的问题,假设你有上面的构造函数。如果您使用 move-ctor(2),您显然会节省大量副本。请注意,这里是 moving 原始向量中数据的所有权,因此请记住您的用例。

多少优势

我只想说很多。

【讨论】:

  • 在您的转发构造函数设计中,std::is_constructible&lt;myVec&lt;int&gt;, std::string&gt;true_type,即使您无法从 string 构造 myVec&lt;int&gt;。有没有办法解决这个问题?
  • @HowardHinnant 删除了我在此处使用完美转发的建议。我想我们必须在这里使用 enable_if 或约束来将 T 限制为可用于构造 vec 的内容。
  • @HowardHinnant 你可能想看看stackoverflow.com/questions/39645986/…。非常好的解释imo。
【解决方案2】:

在您的情况下,性能变化为零,因为两种情况下的输入都是const

通常,如果正确使用移动构造函数,收益会很大,因为不会有任何不必要的复制和分配——std::vector 的每个实例一个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多