【问题标题】:C++ how to avoid ambiguous move constructorsC ++如何避免模棱两可的移动构造函数
【发布时间】:2016-05-23 22:30:56
【问题描述】:

我的课程有几个字段,assignment c-tormove c-tor

class A{
    std::vector<int> numbers;
    int k;


public:

    A(std::vector<int> &&numbers, const int k):
        numbers(numbers), // fast
        k(k)
    {
        // logic
    }

    A(const std::vector<int> &numbers, const int k):
        A(std::move(std::vector<int>(numbers)), k) // copy-and-move vector
    {
        // empty
    }
};

我想将logic 保留在一个c-tor 中并从其他人那里调用它。 另外,我想支持快速move-semantics。而且我必须在assignment c-tor 中明确地copy-and-move 参数。

有什么办法可以避免这种嵌套结构并保留我上面列出的所有优点?

【问题讨论】:

  • 你忘了std::move 所以你的构造函数使用&amp;&amp; 实际上做了一个副本。您不必显式复制和移动赋值变体,不确定为什么要这样做。
  • @MooingDuck 为什么? vector 有一个 move c-tor 接受 std::vector&lt;T&gt; &amp;&amp; 作为参数。为什么要移动已经移动的值?
  • @LibertyPaul 它有一个名字,所以它是一个左值:你需要 std::move 在对std::vector&lt;int&gt;()的调用中将它提升为右值

标签: c++11 constructor move-semantics


【解决方案1】:

您可以将一个构造函数委托给另一个构造函数:

struct A
{
    A(const std::vector<int> & v) : A(std::vector<int>(v)) {}

    A(std::vector<int> && v)
    : v_(std::move(v))
    {
        // logic
    }

    // ...
};

移动构造函数现在已经尽可能快了,并且复制构造函数比同时拼写两个构造函数的移动要多一步。但是,如果您愿意支付额外的费用,您不妨只拥有一个构造函数:

struct A
{
    A(std::vector<int> v)
    : v_(std::move(v))
    {
        // logic
    }
};

另一种方法是将通用代码放入一个函数中,然后从两个构造函数中调用它。

【讨论】:

  • std::vector&lt;int&gt;(v) 是否产生 std::vector&lt;int&gt; &amp;&amp;?如果是,我为什么要再次移动它? vector constructor 不接受我们收到的std::vector&lt;int&gt; &amp;&amp; 作为参数吗?
  • @LibertyPaul:任何有名字的东西都是左值。仅仅因为参数要求提供的值是右值并不意味着它也是右值。
  • @kfsone: 否:std::move 是一个函数,函数调用的结果是一个表达式。表达式永远不是引用。正确的说法是std::move 将任何值变成右值。
猜你喜欢
  • 2021-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-09
  • 2016-04-26
  • 2015-01-23
  • 1970-01-01
相关资源
最近更新 更多