我正在进行演示,演示各种C ++优化,并附有const
允许它们的示例。
考虑以下代码:
对象
class Object {
int i1;
int i2;
public:
Object(int i1_, int i2_) : i1(i1_), i2(i2_) {}
int getI1() const { return i1; }
int getI2() const { return i2; }
std::pair<int, int> calculate() const {
return std::pair<int, int>(i1 + i2, i1 * i2);
}
};
constopt.cpp
#include <iostream>
#include "object.h"
int main() {
Object o(10, 20);
std::cout << o.getI1() << " + " << o.getI2() << " = "
<< o.calculate().first << std::endl
<< o.getI1() << " * " << o.getI2() << " = "
<< o.calculate().second << std::endl;
return 0;
}
内联
calculate()
时,一切正常,G ++将常量(10和20)直接传递给operator <<
缓存getI1()
和getI2()
调用:mov $0xa,%esi
mov $0x601080,%edi
callq 0x400740 <_ZNSolsEi@plt>
但是,当我将
calculate()
移到一个单独的翻译单元时,它会强制将i1
和i2
提取两次(在o.calculate().first
之前和之后):mov (%rsp),%esi
mov 0x4(%rsp),%r14d
mov $0x601080,%edi
callq 0x400740 <_ZNSolsEi@plt>
我看不出有什么区别,因为
getI1()
不依赖于calculate()
可能产生的任何副作用,并且即使Object
在单独的翻译单元中,calculate()
仍应是const。在这种情况下,G ++是否不够智能或没有资格执行优化?我推测它可以缓存
getI1()
,而getI2()
调用来自该答案:How does const after a function optimize the program?我使用的是gcc版本4.8.1。我已经尝试了-Os和-O2。
在这种情况下,似乎在GCC优化器中未使用
const
。相反,它会进行自己的挖掘(无法在不同的翻译单元中执行),并搜索pure and const functions。可以使用__attribute__((const))
手动标记功能。消除多余的getI*()
调用的阶段称为FRE(完全冗余消除)。 最佳答案
因为getI1()不依赖可通过calculate()创建的任何副作用
不管是否做,C ++标准都未指定。
即使在调用getI1()
之前将getI2()
和calculate()
写入流中,在C ++中,函数参数的求值顺序也未指定。这意味着在对calculate()
进行任何实际写入之前,允许编译器以任何顺序对getI1()
和getI2()
和std::cout
进行所有调用。如果它决定在调用calculate()
或getI1()
之前对getI2()
进行一次或两次调用,则不能假定i1
和i2
的值未更改。
如果拆分表达式,则编译器应该能够看到i1
和i2
在调用calculate()
之前不能更改:
// this statement uses i1 and i2 before they can possibly be changed
std::cout << o.getI1() << " + " << o.getI2() << " = ";
// this statement might mutate i1 and i2
std::cout << o.calculate().first << std::endl
<< o.getI1() << " * " << o.getI2() << " = "
<< o.calculate().second << std::endl;
即使在单独的转换单元中有calculate()的情况下,Object也是常量。
但是您实际上并没有声明
o
为const
。调用
const
成员函数并不能保证不能更改成员,这更多是调用方与函数之间的非正式合同,而不是保证。关于c++ - G++:转移到另一个翻译单元会破坏“常量优化”吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29419563/