gpt4 book ai didi

c++ - 二元运算符返回 Xvalue 而不是 PRvalue?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:51:08 26 4
gpt4 key购买 nike

根据 this博客——我意识到这是旧的,如果它不再被认为是相关的,请告诉我——实现二元运算符的最佳方法如下...

// 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

在它们都是矩阵的地方,我最终得到了许多我认为没有必要的移动构造函数和析构函数调用。如果所有采用右值矩阵的 operator+ 的返回类型都更改为 Matrix&&,则消除了构造函数的所有移动,并且只需要一个析构函数调用。

我制作了一个简单的程序,用代码 here 来展示这两种实现方式.

如果这样做是错误的/不好的,谁能解释一下,为什么?我想不出为什么不这样做的原因。它节省了许多构造函数和析构函数调用,并且似乎没有破坏任何东西。

最佳答案

您在这里使用移动构造函数对您的代码进行了修改。矩阵加法可以安全地完成,根本不需要移动构造函数,而且编译器足够聪明,可以优化它。

下面是一些测试代码来证明我在说什么:

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

我使用 GCC: (GNU) 4.9.0 20131110 (experimental) 如下:g++ -O3 main.cpp -S

输出程序集如下所示:

_main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $176, %esp
call ___main
fnstcw 14(%esp)
fldz
fadd %st(0), %st
fadds LC0
fadds LC0
fsts 140(%esp)
movl 140(%esp), %eax
fsts 144(%esp)
movl %eax, 20(%esp)
movl 144(%esp), %eax
fsts 148(%esp)
movl %eax, 24(%esp)
fsts 152(%esp)
movl 148(%esp), %eax
fsts 156(%esp)
movl %eax, 28(%esp)
fsts 160(%esp)
movl 152(%esp), %eax
fsts 164(%esp)
movl %eax, 32(%esp)
fsts 168(%esp)
movl 156(%esp), %eax
fstps 172(%esp)
movl %eax, 36(%esp)
movl 160(%esp), %eax
flds 24(%esp)
movl %eax, 40(%esp)
movl 164(%esp), %eax
movl %eax, 44(%esp)
movl 168(%esp), %eax
movl %eax, 48(%esp)
movl 172(%esp), %eax
movl %eax, 52(%esp)
movzwl 14(%esp), %eax
movb $12, %ah
movw %ax, 12(%esp)
fldcw 12(%esp)
fistpl 8(%esp)
fldcw 14(%esp)
movl 8(%esp), %edx
flds 20(%esp)
fldcw 12(%esp)
fistpl 8(%esp)
fldcw 14(%esp)
movl 8(%esp), %eax
flds 28(%esp)
addl %eax, %edx
fldcw 12(%esp)
fistpl 8(%esp)
fldcw 14(%esp)
movl 8(%esp), %eax
flds 32(%esp)
addl %eax, %edx
fldcw 12(%esp)
fistpl 8(%esp)
fldcw 14(%esp)
movl 8(%esp), %eax
flds 36(%esp)
addl %eax, %edx
fldcw 12(%esp)
fistpl 8(%esp)
fldcw 14(%esp)
movl 8(%esp), %eax
flds 40(%esp)
addl %eax, %edx
fldcw 12(%esp)
fistpl 8(%esp)
fldcw 14(%esp)
movl 8(%esp), %eax
flds 44(%esp)
addl %eax, %edx
fldcw 12(%esp)
fistpl 8(%esp)
fldcw 14(%esp)
movl 8(%esp), %eax
flds 48(%esp)
addl %eax, %edx
fldcw 12(%esp)
fistpl 8(%esp)
fldcw 14(%esp)
movl 8(%esp), %eax
flds 52(%esp)
addl %eax, %edx
fldcw 12(%esp)
fistpl 8(%esp)
fldcw 14(%esp)
movl 8(%esp), %eax
leave
addl %edx, %eax
ret

根本没有任何复制/移动构造函数或任何函数调用的踪迹。一切都展开成快速的数学研磨指令流。

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

关于c++ - 二元运算符返回 Xvalue 而不是 PRvalue?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22237275/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com