Question

Folks,

I was reading "Thinking in C++" (Chap - Inline functions), where I encountered this statement.

"The compiler also cannot perform inlining if the address of the function is taken implicitly or explicitly".

What does that mean by "taking address of function implicitly or explicitly" ?
Why it is not possible to inline in this case ?

Thanks.

Was it helpful?

Solution

Actually, the quote may mislead.

If a function address is taken, then it is necessary to generate the function in the library/executable, because the execution of a function by its address consist in jumping the instruction pointer to the block of code describing the function.

However, it certainly does not prevent the compiler to inline the function in other places, when called directly.

First, a review:

// Explicit:
void foo();

void (*func_ptr)() = foo;


// Implicit
struct Foo { virtual void bar() {} }; // address used in V-Table

Second, inlining examples:

int main() {
  (*func_ptr)(); // probably not inlined as the compiler can difficultly assert
                 // that nobody may modified it... since it's non-const.

  foo(); // might be inlined

  Foo f;
  f.bar(); // might be inlined (the exact type of `f` is known)
           // this is called, "devirtualizing"

  Foo& g = accessSomeFoo();
  g.bar(); // probably not inlined unless the compiler can assert
           // the type returned by accessSomeFoo
           // (which requires knowing its definition)
}

OTHER TIPS

Taking the address of a function means assigning it to a function pointer. This can happen explicitly, as in the linked examples. I am not sure what the author means by "implicitly" - maybe things like passing a function as a parameter to another function.

If the address of the function is taken, it must have an address in the first place. Since inlining means basically substituting calls to the function with a copy of its body, after such a transformation the function no more exists, thus has no address - only n distinct copies of identical code in places where there used to be calls to that function. Thus if a function's address is used in any way, it can't be inlined.

I'm not sure if that is entirely true. However, if you take the address of a function, that function needs to exist in memory complete with the function's preamble and cleanup code. It's this preamble and cleanup that's omitted when inlining. And you get a whole load of optimisation possibilites when inlined.

But a modern compiler should still be able to inline the function wherever it's possible to inline it. Consider:

int compare (int a, int b)
{
  return a compared to b
}

int main ()
{
  a = array of ints

  qsort (a, compare); // take address of compare function, thus compare function exists in
                      // app as a proper function

  compare (value1, value2); // there's no reason why this can't be inlined
}

I think the quote should be more explicit about what can't be inlined:

A function that is called via a function pointer can not be inlined.

This is because there is no way to determine at compile time what function to inline at the point of the indirect call (the call via the function pointer). This doesn't mean to say that the function that has been pointed to by a function pointer can't be inlined wherever it is called directly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top