在C++中有没有办法声明一个函数没有副作用?考虑:
LOG("message").SetCategory(GetCategory());
Run Code Online (Sandbox Code Playgroud)
现在假设发布版本中的LOG宏创建了一个NullLogEntry对象,该对象将SetCategory()定义为空函数.所以基本上整个表达式都可以(并且应该)被优化掉 - 从理论上说,GetCategory()调用可能会有一些副作用,所以我想编译器不允许抛弃它.
另一个示例可能是忽略其某些(或全部)参数的函数模板特化,但由于可能的副作用,编译器不允许在调用站点保存此类参数的评估.
我对吗?或者编译器能否最终优化此类调用?如果没有,有没有办法提示编译器这个函数没有副作用,所以如果忽略返回值那么可以跳过整个调用?
Dav*_*eas 17
没有标准的方法可以这样做,但是有些编译器有注释可以用来实现这种效果,例如,在GCC中你可以__attribute_pure__在函数中使用标签(或者__attribute__((pure)))告诉编译器函数是纯的(即有无副作用).这在标准C库中广泛使用,例如:
char * str = get_some_string();
for ( int i = 0; i < strlen( str ); ++i ) {
str[i] = toupper(str[i]);
}
Run Code Online (Sandbox Code Playgroud)
可以通过编译器优化为:
char * str = get_some_string();
int __length = strlen( str );
for ( int i = 0; i < __length; ++ i ) {
str[i] = toupper(str[i]);
}
Run Code Online (Sandbox Code Playgroud)
该函数在string.h头中声明为:
extern size_t strlen (__const char *__s)
__THROW __attribute_pure__ __nonnull ((1));
Run Code Online (Sandbox Code Playgroud)
如果__THROW是C++编译器解析函数,则抛出异常,并__nonnull((1))告诉编译器第一个参数不应为null(即如果参数为null且使用-Wnonnull标志则触发警告).
编译器无法优化对不透明函数的调用。但是,如果GetCategory是内联的,并且因此在调用站点可见,则允许编译器,并且在大多数情况下,如果编译器发现它没有副作用,则会优化它,但不强制这样做。
为了 100% 确定地实现您想要的目标,您需要将整个语句包装在一个宏中,该宏将针对您的发布配置计算出一个空语句。