C++: optimizing function with no side effects

北战南征 提交于 2019-11-27 03:21:15

问题


Is there a way in C++ to declare that a function has no side effects? Consider:

LOG("message").SetCategory(GetCategory()); 

Now suppose that the LOG macro in release builds creates a NullLogEntry object that has SetCategory() defined as an empty function. So basically the whole expression could (and should) be optimized away -- expcept that, in theory, the GetCategory() call may have some side effects, so I guess the compiler is not permitted to just throw it away.

Another example could be a function template specialization that ignores some (or all) of its arguments, yet the compiler is not allowed to save the evaluation of such arguments at the call site due to possible side effects.

Am I right? Or can compilers optimize away such calls anyway? If not, is there a way to hint the compiler that this function has no side effects, so if the return value is ignored then the whole call can be skipped?


回答1:


There is no standard way of doing so, but some compilers have annotations that you can use to that effect, for example, in GCC you can use the __attribute_pure__ tag in a function (alternatively __attribute__((pure))) to tell the compiler that the function is pure (i.e. has no side effects). That is used in the standard C library extensively, so that for example:

char * str = get_some_string();
for ( int i = 0; i < strlen( str ); ++i ) {
    str[i] = toupper(str[i]);
}

Can be optimized by the compiler into:

char * str = get_some_string();
int __length = strlen( str );
for ( int i = 0; i < __length; ++ i ) {
   str[i] = toupper(str[i]);
}

The function is declared in the string.h header as:

extern size_t strlen (__const char *__s)
     __THROW __attribute_pure__ __nonnull ((1));

Where __THROW is a no throw exception in case that it is a C++ compiler parsing the function, and __nonnull((1)) tells the compiler that the first argument should not be null (i.e. trigger a warning if the argument is null and -Wnonnull flag is used).




回答2:


The compiler cannot optimize away a call to the opaque function. However, if GetCategory is inline, and, hence visible at the call site, the compiler is allowed to, and it most cases, will optimize it away if it sees that it doesn't have side effects, but is not mandated to do so.

To achieve what you want with 100% certainty you need to wrap the entire statement in a macro that will evaluate to an empty statement for your release configuration.




回答3:


This is a know issue with having Debug Mode code.

The only reliable solution (for function calls) is to wrap all the debugging code within the macro itself.

For example, you could perhaps use the following code instead:

LOG("message", GetCategory());

Then the preprocessor would wipe out the whole statement in Release, and you would not have to worry about this any longer.



来源:https://stackoverflow.com/questions/6623879/c-optimizing-function-with-no-side-effects

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!