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

Lun*_*oul 0 c++ operator-overloading rvalue-reference c++11

虽然在我的一些类中实现方法和运算符重载以利用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);
    }
Run Code Online (Sandbox Code Playgroud)

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

Bar*_*rry 5

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

    matrix_2_2 operator*(const matrix_2_2& m) const;
Run Code Online (Sandbox Code Playgroud)

你的类是POD - 在这种情况下,移动和副本之间没有区别,因此利用移动语义来获得收益是没有可能的.您正在获得代码复杂性,但不会提高性能.如果this&或者&&...... 你的代码应该做什么没有逻辑上的区别

这个:

matrix_2_2 operator*(matrix_2_2&& m) &&
{
    matrix_2_2 res;
    ...
    return std::move(res);
}
Run Code Online (Sandbox Code Playgroud)

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

matrix_2_2 product = some_matrix() * some_other_matrix();
Run Code Online (Sandbox Code Playgroud)

而不是简单地res在原地构建product.

  • @LunaticSoul如果你有一个更复杂的场景,其中移动语义适用,我只是问一个关于那个场景的问题.当然,如果您发现自己编写*相同*代码,则可以轻松删除副本. (2认同)