- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
根据 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/
[N4687] 3.9 [defns.dynamic.type] dynamic type 〈glvalue〉 type of the most derived object (4.5) to whi
我的代码如下: #include #include int main(){ for(int& v : std::vector{1,3,5,10}) { std::cout
我最近一直在仔细研究 C++ 类别。 lvalue 和 rvalue 之间的区别似乎很清楚,但是当谈到 prvalue 和 xvalue 时,我感到困惑。 给出下面的例子: #include usi
根据 this博客——我意识到这是旧的,如果它不再被认为是相关的,请告诉我——实现二元运算符的最佳方法如下... // The "usual implementation" Matrix operat
在 C++11 5.1 Primary Expressions 中声明: The type of [an id-expression] is the type of the identifier. T
对于这个问题的广泛性,我很抱歉,只是所有这些细节都是紧密相关的.. 我一直在努力理解具体两个值类别(xvalues 和 prvalues)之间的区别,但我仍然感到困惑。 无论如何,我试图为自己建立的关
有没有办法定义一个只处理 xvalue 或 prvalue 的函数(或者这里是异或)? 例如,假设我有一个方法 f(foo&& f),我如何声明 f 绑定(bind) xvalue 类型并拒绝 prv
几个星期以来,我一直在仔细研究右值和右值引用。我越来越有信心,我对以下两者之间的区别有了一定的了解: 定义变量或函数参数的类型(即 int x; 与 int && x = …; 表达式的表达式类别,包
这个问题是在我研究 decltype 行为及其派生表达式类型的规则时提出的。如果表达式是纯右值,是否有任何理由不提升通用 cv 限定符?类型。例如:- 在下面的代码中,表达式 i+j 是由declty
C++标准定义删除了以下函数; template void ref(const T&&) = delete; template void cref(const T&&) = delete; 这是为
What are rvalues, lvalues, xvalues, glvalues, and prvalues?很好地概述了右值/左值的分类,最近对该问题的回答之一 (https://stack
在 C++03 中,表达式可以是 rvalue 或 lvalue。 在 C++11 中,表达式可以是: 右值 左值 xvalue glvalue prvalue 两个类别变成了五个类别。 这些新的表达
decltype(1+2) 是否声明了一个 xvalue 或 prvalue? cppreference 说,decltype(expression) 将声明:1. T&& if expression
我是一名优秀的程序员,十分优秀!