在C++中有没有办法声明一个函数没有副作用?考虑:
LOG("message").SetCategory(GetCategory());
Run Code Online (Sandbox Code Playgroud)
现在假设发布版本中的LOG宏创建了一个NullLogEntry对象,该对象将SetCategory()定义为空函数.所以基本上整个表达式都可以(并且应该)被优化掉 - 从理论上说,GetCategory()调用可能会有一些副作用,所以我想编译器不允许抛弃它.
另一个示例可能是忽略其某些(或全部)参数的函数模板特化,但由于可能的副作用,编译器不允许在调用站点保存此类参数的评估.
我对吗?或者编译器能否最终优化此类调用?如果没有,有没有办法提示编译器这个函数没有副作用,所以如果忽略返回值那么可以跳过整个调用?
下面声明norm的C++ vector类中的成员函数标记为const和(据我所知)不包含任何副作用.
template <unsigned int N>
struct vector {
double v[N];
double norm() const {
double ret = 0;
for (int i=0; i<N; ++i) {
ret += v[i]*v[i];
}
return ret;
}
};
double test(const vector<100>& x) {
return x.norm() + x.norm();
}
Run Code Online (Sandbox Code Playgroud)
如果我打电话norm多次上const的实例vector(见test上面的函数)与GCC编译器(5.4版本)和优化开启(即-O3),那么编译器内联norm,但仍计算的结果norm多次,即使结果不应该改变.为什么编译器不优化第二次调用norm而只计算一次这个结果?这个答案似乎表明,如果编译器确定该norm函数没有任何副作用,编译器应该执行此优化.为什么在这种情况下不会发生这种情况?
请注意,我正在使用Compiler Explorer确定编译器生成的内容,并且下面给出了gcc版本5.4的程序集输出.clang编译器给出了类似的结果.另请注意,如果我使用gcc的编译器属性手动标记norm为使用const函数__attribute__((const)),那么第二次调用会根据需要进行优化,但我的问题是为什么gcc(和clang)不会自动执行此操作,因为norm定义可用?
test(vector<100u>&): …Run Code Online (Sandbox Code Playgroud)