【问题标题】:how to implement movable overloads without violating the DRY principle in C++?如何在不违反 C++ 中的 DRY 原则的情况下实现可移动重载?
【发布时间】:2015-05-16 14:11:00
【问题描述】:

在我的一些类中实现方法和运算符重载以利用 C++ 中的右值引用时,我经常编写一些设计不佳的代码,违反了 DRY 原则。下面的代码 sn-p 有什么更好的选择? (这段代码只是为了说明问题)

class matrix_2_2
{
    int _m[2][2];

public:

    matrix_2_2 operator*(const matrix_2_2& m) const &
    {   
        matrix_2_2 res;
        for(int i = 0 ; i < 2 ; i ++)
            for(int j = 0 ; j < 2 ; j++)
                for(int k = 0 ; k < 2 ; k++)
                    res._m[i][j] = (res._m[i][j] + _m[i][k]*m._m[k][j]);

        return res;
    }

    matrix_2_2 operator*(matrix_2_2&& m) &&
    {
        matrix_2_2 res;
        for(int i = 0 ; i < 2 ; i ++)
            for(int j = 0 ; j < 2 ; j++)
                for(int k = 0 ; k < 2 ; k++)
                    res._m[i][j] = (res._m[i][j] + _m[i][k]*m._m[k][j]);

        return move(res);
    }

这段代码在实现细节中出现了很多重复,我想封装逻辑并在不同的重载中重用它,而不会因为右值到左值的隐式转换而失去可移动的优势。

【问题讨论】:

  • 您可以定义第三个函数并让两个operator* 调用它。
  • @Lingxi,在这种情况下我会通过const matrix_2_2&amp;matrix_2_2&amp;&amp;?我考虑过这个替代方案,但无法就函数传递的类型得出任何结论。
  • 这种情况不需要重载。

标签: c++ c++11 operator-overloading rvalue-reference


【解决方案1】:

更好的选择是完全删除右值限定的operator*,只保留一个operator*,这个:

    matrix_2_2 operator*(const matrix_2_2& m) const;

您的类是一个 POD - 在这种情况下,移动和复制之间没有区别,因此利用移动语义对您来说没有任何好处。您在代码复杂性方面获得了提升,但在性能方面却没有。如果this&amp;&amp;&amp;,你的代码应该做什么确实没有逻辑上的区别...

还有,这个:

matrix_2_2 operator*(matrix_2_2&& m) &&
{
    matrix_2_2 res;
    ...
    return std::move(res);
}

这不是正确的写法,因为最后一个move 使得无法进行命名的返回值优化,所以你正在为类似的代码做一个额外的move

matrix_2_2 product = some_matrix() * some_other_matrix();

而不是简单地在product 中就地构造res

【讨论】:

  • 好的,在这个例子中,这个类是一个 POD,但在更复杂的场景中它不会是,我想知道一个更好的设计来重用不同重载中的核心实现细节,同时也利用右值优化。
  • 关于return std::move(res); 不知道会伤害返回值优化,谢谢提示。
  • @LunaticSoul 如果您有一个更复杂的应用移动语义的场景,我只想问一个关于该场景的问题。当然,如果您发现自己在编写相同代码,您可以轻松删除重复的代码。
  • @Barry 同意了。矩阵的例子很特别。
  • 我赞成,因为这是唯一合理的结论,但这与 POD 无关。重载除了复杂性之外没有任何贡献。
猜你喜欢
  • 1970-01-01
  • 2018-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-20
  • 2012-09-15
相关资源
最近更新 更多