如何实现可移动的重载而不违反C ++中的DRY原则?

时间:2015-05-16 14:11:00

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

虽然在我的一些类中实现方法和运算符重载以利用C ++中的右值引用,但我经常编写一些设计不良而违反DRY原则的代码。对于下面的代码片段,什么是更好的替代方案? (此代码仅用于说明问题)

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);
    }

这段代码在实现细节中提供了大量的重复,我想封装逻辑并在不同的重载中重用它,而不会因为左值的重要性转换而失去可移动的优势。

1 个答案:

答案 0 :(得分:5)

更好的选择是完全删除符合rvalue的operator*并且只拥有一个operator*,这一个:

    matrix_2_2 operator*(const matrix_2_2& m) const;

你的类是POD - 在这种情况下,移动和副本之间没有区别,所以通过利用移动语义来获得收益是没有可能的。您获得了代码复杂性,但没有获得性能。如果this&&&,则代码应该执行的操作确实没有逻辑差异...

另外,这个:

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

不是正确的写法,因为最后move使得无法进行命名的返回值优化,因此您需要为以下代码执行额外的move: / p>

matrix_2_2 product = some_matrix() * some_other_matrix();

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