二进制操作员返回XVALUE而不是prvalue
Binary Operators Return Xvalue Instead of PRvalue?
根据此博客 - 我意识到这是旧的,如果不再考虑相关的话,请告诉我 - 实施二进制操作员的最佳方法是以下...
// 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
在它们都是矩阵的地方,我最终得到了我不认为是必要的许多移动构造函数和驱动器调用。如果将所有操作员的返回类型更改为矩阵& amp;',您消除了所有移动构造函数,只需要一个单个驱动器调用。
我制作了一个简单的程序,可以在此处使用代码显示两个实现。
有人可以解释这样做是否错误/不好,为什么?我想不出一个原因,为什么不这样做。它节省了许多构造函数和破坏器调用,并且似乎并没有打破任何内容。
您在此处使用移动构造函数对代码进行修饰。矩阵添加可以安全地完成,而根本没有移动构造函数,并且编译器足够聪明以将其优化。
这是一些测试代码,可以证明我在说什么:
#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
根本没有任何复制/移动构造函数或任何功能调用的单个跟踪。一切都将其展开为快速的数学磨练指令流。
认真地说,无需为R值编写其他处理程序。编译器没有它们制作完美的代码。
相关文章:
- 返回指向对象的指针的函数调用是否为 prvalue?
- 一元*运算符的操作数是否期望一个 prvalue
- 函数返回的 rvalue 引用(表达式)是 xvalue - 但没有标识?
- 使用 prvalue 创建shared_pointer
- 初始化声明符是 prvalue 表达式吗?
- "xvalue has identity"是什么意思?
- 现代C ++,对xValue的理解
- XVALUE来自类成员访问表达式
- 声明规则定义了lvalue或prvalue
- 为什么在提到 prvalue 时,它在这里使用术语"object"?
- 为什么函数调用是xvalue(如果返回类型为rvalue)
- C++11: "decltype(1+2)"声明 xvalue 还是 prvalue?
- 如何定义xvalue混合类别
- std::move() and xvalue in C++
- 我们如何测试是否可以使用 prvalue 调用某种类型的表达式
- 将非类非数组 prvalue 转换为符合 cv 条件的类型是否合法?
- xvalue上的下标的值类别
- 是C 11中XVALUE的数据成员
- 二进制操作员返回XVALUE而不是prvalue
- 如何定义一个仅绑定 xvalue 或 prvalue 而不绑定两者的函数