运算符重载关联性编译器优化
Operator overloading associativity compiler optimization
我不熟悉 C++ 中如何定义加法和乘法运算符的细节,我也不知道编译器可以或不可以使用哪些信息来优化低效的运算顺序。
假设我们有一个矩阵数据类型,它实现了按元素乘以标量(即按标量缩放矩阵)。如果我们有以下代码片段:
Matrix a;
float b = /* value set at runtime */;
float c = /* value set at runtime */;
a = a * b * c;
如果我们天真地从左到右评估这个表达式,我们会先将 a
缩放 b
,然后将其缩放 c
,而不是缩放 a
通过 b
和 c
的乘积。编译器是否能够选择后者
(更有效)行为而不是前者?
Godbolt 上的一些实验似乎发现,最新版本的 GCC 和 Clang 为 a * b * c
生成的代码与为 (a * b) * c
生成的代码相同,比为 [=12] 生成的代码长=],因此看起来不,编译器不够智能,无法执行您要求的优化。
您可以自己加上括号 b * c
。一个更复杂的解决方案是让 *
运算符生成一个表达式模板,该模板将在评估之前进行优化,因此即使用户键入 (a * b) * c
您的库也会在评估之前将其重新排列为 a * (b * c)
.
我不熟悉 C++ 中如何定义加法和乘法运算符的细节,我也不知道编译器可以或不可以使用哪些信息来优化低效的运算顺序。
假设我们有一个矩阵数据类型,它实现了按元素乘以标量(即按标量缩放矩阵)。如果我们有以下代码片段:
Matrix a;
float b = /* value set at runtime */;
float c = /* value set at runtime */;
a = a * b * c;
如果我们天真地从左到右评估这个表达式,我们会先将 a
缩放 b
,然后将其缩放 c
,而不是缩放 a
通过 b
和 c
的乘积。编译器是否能够选择后者
(更有效)行为而不是前者?
Godbolt 上的一些实验似乎发现,最新版本的 GCC 和 Clang 为 a * b * c
生成的代码与为 (a * b) * c
生成的代码相同,比为 [=12] 生成的代码长=],因此看起来不,编译器不够智能,无法执行您要求的优化。
您可以自己加上括号 b * c
。一个更复杂的解决方案是让 *
运算符生成一个表达式模板,该模板将在评估之前进行优化,因此即使用户键入 (a * b) * c
您的库也会在评估之前将其重新排列为 a * (b * c)
.