Are modern C++ compilers able to avoid calling a const function twice under some conditions?

后端 未结 5 868
被撕碎了的回忆
被撕碎了的回忆 2021-02-05 01:10

For instance, if I have this code:

class SomeDataProcessor
{
public:
    bool calc(const SomeData & d1, const SomeData & d2) const;
private:
    //Some n         


        
相关标签:
5条回答
  • 2021-02-05 01:36

    Yes, absolutely.

    Compilers do this all the time, and more.

    For example, if all your function did were return true, and its definition were visible to the compiler at the callsite, the entire function call would probably be elided, resulting in just:

    someObscureFunction(true, true);
    

    A program for which the compiler has sufficient information may be "optimised" from a quite complex chain of tasks down to perhaps one or two instructions. Now, actually operating on member variables is pushing the optimiser to its limit to some degree, but if the variables are private, are given a known initial value, and are not mutated by any other member function, I don't see why a compiler couldn't just inline its known value if it wanted to. Compilers are very, very smart.

    People think that a compiled program is a one-to-one mapping of lines in your source code, but this is almost never true. The entire purpose of C++ is that it is an abstraction of what your computer's actually going to be doing when it runs your program.

    0 讨论(0)
  • 2021-02-05 01:42

    GCC has the pure attribute (used as __attribute__((pure))) for functions which tells the compiler that redundant calls can be eliminated. It's used e.g. on strlen.

    I'm not aware of any compiler doing this automatically, especially considering the fact that the functions to be called may not be available in source form, and the object file formats contain no metadata about whether a function is pure or not.

    0 讨论(0)
  • 2021-02-05 01:53

    Yes, modern C compilers can elide redundant function calls if and only if they can prove that such an optimization behaves as-if the original program semantics were followed. For example, that means means they could eliminate multiple calls to the same function with the same arguments, if the function has no side-effects and if its return value depends only on the arguments.

    Now, you asked specifically about const - this is mostly useful to the developer, and not the coder. A const function is a hints that the method doesn't modify the object it is called on, and const arguments are hints that the arguments are not modified. However, the function may (legally1) cast away the const-ness of the this pointer or of its arguments. So the compiler can't rely on it.

    Furthermore, even if const objects passed to a function really were never modified within that function, and const functions never modified the receiver object, the method could easily rely on mutable global data (and could mutate such data). Consider, for example, a function that returns the current time, or which increments a global counter.

    So the const declarations help the programmer, not the compiler2.

    However, the compiler might be able to use other tricks to prove the calls are redundant:

    • The function may be in the same compilation unit as the caller, allowing the compiler to inspect it and determine exactly what it relies on. The ultimate form of this is inlining: the function body may be moved into the caller at which point the optimizer can remove redundant code from later calls (up to an including all the code from those calls entirely and perhaps all or port of the original call too).
    • The toolchain may use some type of link-time-optimization, which effectively allows the type of analysis described in the point above even for functions and callers in different compilation units. This could allow this optimization for any code present when the final executable is being generated.
    • The compiler may allow the user to annotate a function with an attribute that informs the compiler that it may treat the function as not having side-effects. For example, gcc provides the pure and const function attributes which inform gcc that the functions has no side effects, and depend only on their parameters (and on global variables, in the case of pure).

    1 Usually, as long as the object wasn't originally defined as const.

    2 There is at one sense in which const definitions do help the compiler: they can put global objects defined as const into a read-only section of the executable (if such a feature exists) and also combine such objects when they are equal (e.g., identical string constants).

    0 讨论(0)
  • 2021-02-05 01:56

    No, the compiler is not allowed to do that in this case. The const only means you do not change the state of the object the method belongs to. However, invoking this method multiple times with the same input parameters might give different results. For example, think of a method that produces a random result.

    0 讨论(0)
  • 2021-02-05 02:01

    No, given the shown code, the compiler cannot guarantee that the proposed optimization will have no observable differences, and no modern compiler will be able to optimize away the second function call.

    A very simple example: this class method might use a random number generator, and save the result in some private buffer, that some other part of the code reads later on. Obviously, eliminating a function call now results in fewer randomly-generated values being placed in that buffer.

    In other words, just because a class method is const does not mean that it has no observable side effects when it's called.

    0 讨论(0)
提交回复
热议问题