【发布时间】:2018-03-30 23:53:31
【问题描述】:
我不熟悉 C++ 中如何定义加法和乘法运算符的细节,也不知道编译器可以使用或不使用哪些信息来优化低效的操作顺序。
假设我们有一个矩阵数据类型,它实现了按元素乘以标量(即按标量缩放矩阵)。如果我们有如下代码sn-p:
Matrix a;
float b = /* value set at runtime */;
float c = /* value set at runtime */;
a = a * b * c;
如果我们天真地从左到右评估此表达式,我们将首先将a 缩放b,然后将其缩放c,而不是将a 缩放为b 和@987654328 的乘积@。编译器是否能够选择后者
(更有效的)行为而不是前者?
【问题讨论】:
-
编译器一般不理解用户定义函数的语义。需要一个自动定理证明器来证明将表达式重写为
a * c * b不会改变其含义;编译器不太可能实现它。 -
我记得听过一个关于某种实验性编译器的故事,它能够将
int s = 0; for (int i = 0; i < n; ++i) s += i;重写为s = n*(n+1)/2;我强烈怀疑这是一个都市传说。 -
如果 C++ 将乘法和加法定义为必须是关联的操作,那么我认为编译器将表达式重写为
a * (b * c)或c * a * b是公平的游戏。当然,编译器必须能够确定这些排序之一更有效。同样,我对编译器优化了解不多,所以这只是猜测。 -
嗯,我刚刚注意到 stackoverflow.com/questions/6430448/… 。仍然不知道 -fassociative-math 是否有帮助
-
C++ 对 内置 运算符做出了某些假设。用户定义的重载运算符只是名字很有趣的函数;不对他们的行为做出任何假设。
a * b * c只是operator*(operator*(a, b), c)的简写;我假设您的程序定义了operator*(float, Matrix)和operator*(Matrix, float)以及class Matrix
标签: c++ operator-overloading operators compiler-optimization associativity