C++ 二进制运算符返回Xvalue而不是PRvalue?

C++ 二进制运算符返回Xvalue而不是PRvalue?,c++,c++11,C++,C++11,根据博客——我意识到它已经过时了,如果它不再被认为是相关的,请让我知道——实现二进制运算符的最佳方法是以下 // The "usual implementation" Matrix operator+(Matrix const& x, Matrix const& y) { Matrix temp = x; temp += y; return temp; } // --- Handle rvalues --- Matrix operator+(Matrix&&

根据博客——我意识到它已经过时了,如果它不再被认为是相关的,请让我知道——实现二进制运算符的最佳方法是以下

// The "usual implementation"
Matrix operator+(Matrix const& x, Matrix const& y)
{ Matrix temp = x; temp += y; return temp; }

// --- Handle rvalues ---

Matrix operator+(Matrix&& temp, const Matrix& y)
{ temp += y; return std::move(temp); }

Matrix operator+(const Matrix& x, Matrix&& temp)
{ temp += x; return std::move(temp); }

Matrix operator+(Matrix&& temp, Matrix&& y)
{ temp += y; return std::move(temp); }
a + b + c + d
我测试了这个实现,在下面的表达式中

// The "usual implementation"
Matrix operator+(Matrix const& x, Matrix const& y)
{ Matrix temp = x; temp += y; return temp; }

// --- Handle rvalues ---

Matrix operator+(Matrix&& temp, const Matrix& y)
{ temp += y; return std::move(temp); }

Matrix operator+(const Matrix& x, Matrix&& temp)
{ temp += x; return std::move(temp); }

Matrix operator+(Matrix&& temp, Matrix&& y)
{ temp += y; return std::move(temp); }
a + b + c + d
当它们都是矩阵时,我最终得到了许多我认为不必要的move构造函数和析构函数调用。如果采用右值矩阵的所有运算符+上的返回类型都更改为矩阵&&,则消除了所有move-the构造函数,并且只需要一个析构函数调用

我制作了一个简单的程序,用代码显示这两种实现


有人能解释一下这样做是否错误/不好,以及原因吗?我想不出不这样做的理由。它保存了许多构造函数和析构函数调用,并且似乎不会破坏任何东西。

您正在使用move构造函数对代码进行优化。矩阵加法可以在不移动构造函数的情况下安全地完成,而且编译器足够聪明,可以对其进行优化

下面是一些测试代码来证明我所说的:

#include <stdint.h>

class Matrix3
{
public:
    float Mtx[3][3];

    inline Matrix3() {};
    inline Matrix3 operator+( const Matrix3& Matrix ) const
    {
        Matrix3 Result;
        for ( size_t i = 0; i != 3; ++i )
        {
            for ( size_t j = 0; j != 3; ++j )
            {
                Result.Mtx[i][j] = Mtx[i][j] + Matrix.Mtx[i][j];
            }
        }
        return Result;
    }

    virtual int GetResult() const
    {
        int Result = 0;

        for ( size_t i = 0; i != 3; ++i )
        {
            for ( size_t j = 0; j != 3; ++j )
            {
                Result += (int)Mtx[i][j];
            }
        }       

        return Result;
    }
};

int main()
{
    Matrix3 M;

    Matrix3 M1;
    Matrix3 M2;
    Matrix3 M3;
    Matrix3 M4;

    M = M1 + M2 + M3 + M4;

    return M.GetResult();
}
没有任何复制/移动构造函数或任何函数调用的单一跟踪。一切都被展开成一个快速的数学指令流


说真的,没有必要为r值编写额外的处理程序。编译器在没有它们的情况下会生成完美的代码。

操作符+(矩阵常量&x,矩阵常量&y)会返回什么?我希望不是指
temp
。另外,如果有人写
Matrix&&x=a+b+c;剂量测定法(x)他们会过得很不愉快
x
在初始化后很快就会变成一个悬空引用。这有帮助吗?@IgorTandetnik左值引用可以从右值引用初始化吗?@Jay:我在发布后很快就修复了它。你赢了我。不可否认,这是一个相当牵强的场景。操作符+(矩阵常数&x,矩阵常数&y)仍然返回左值,如上所述。在这种情况下,您将得到一个复制构造函数调用和一个移动构造函数调用。编辑:你改变了它。这看起来确实有点令人担忧,但我想不出创建一个矩阵并保存它的理由。如果默认构造函数微不足道,这是正确的,但是如果它将矩阵置零,那么这比我建议的要慢。显然,所有这些选项都取决于您使用的类(Matrix只是链接网站上的一个示例),但我相信如果您按照我发布的路线返回XValues而不是PRValues,那么返回XValues总是更快。