Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are pointers to inline functions allowed?

I have two questions:

1) Why are pointers to inline functions allowed in C++? I have read that the code of inline functions just gets copied to the function call statement and there is no compile-time memory allocation in inline functions. So why can a pointer exist to an inline function, given that there is no fixed memory address for inline functions?

2) Consider the code below:

inline void func()     {     int n=0;     cout<<(&n); }  

Should it not print different values of the address of n each time func() is called? [Because I think that every time inline function code is copied, reallocation of the local variables must be done (whereas in the case of normal functions, reinitialisation takes place)]

I am a beginner and I asked this question for the sake of my concept strengthening. Please correct me if I am wrong anywhere.

like image 639
Madhuchhanda Mandal Avatar asked Jan 19 '17 08:01

Madhuchhanda Mandal


People also ask

What is a pointer inline function?

Its main meaning is to be able to put the definition of a function in a header file without having to deal with "multiple definition" problems at link time. The official way in C99 and C11 to do what you want to achieve is to have the inline definition in the header file, without the static .

Why would you want to use inline functions?

An inline function is one for which the compiler copies the code from the function definition directly into the code of the calling function rather than creating a separate set of instructions in memory. This eliminates call-linkage overhead and can expose significant optimization opportunities.

Why inline functions are useful 1 point?

Inline functions provide following advantages: 1) Function call overhead doesn't occur. 2) It also saves the overhead of push/pop variables on the stack when function is called. 3) It also saves overhead of a return call from a function.

Why are inline functions bad?

inline functions might make it slower: Too much inlining might cause code bloat, which might cause “thrashing” on demand-paged virtual-memory systems. In other words, if the executable size is too big, the system might spend most of its time going out to disk to fetch the next chunk of code.


2 Answers

1) Why pointers to inline functions are allowed in c++?

Because inline functions are functions just like any other, and pointing to them is one of the things that you can do with functions. Inline functions just aren't special in this regard.

I have read that code of inline functions just get copied to the function calling statement and there is no compile time memory allocations in inline functions.

You (and perhaps the material you've read) have mixed two related and similarly named concepts.

An inline function is defined in all translation units that use it, while a non-inline function is defined in one translation unit only as required by the one definition rule. That is what an inline declaration of a function means; it relaxes the one definition rule, but also gives the additional requirement of being defined in all translation units that use it (which would not have been possible if the odr wasn't relaxed).

Inline expansion (or inlining) is an optimization, where a function call is avoided by copying the called function into the frame of the caller. A function call can be expanded inline, whether the function has been declared inline or not. And a function that has been declared inline is not necessarily expanded inline.

However, a function can not be expanded inline in a translation unit where it is not defined (unless link time optimization performs the expansion). Therefore the requirement of being defined in all TUs that the inline declaration allows, also makes possible the inline expansion of the function by allowing the function to be defined in all TUs that invoke it. But the optimization is not guaranteed.

2) Should it not print different values of address of n each time func() is called?

Inline expansion does cause the local variables to be located in the frame of the caller, yes. But their location will differ regardless of expansion if the calls originate from separate frames.

There is typically a regular non-expanded version generated of any function that has been expanded inline. If the address of a function is taken, it will point to that non-expanded function. If the compiler can prove that all calls to a function are inlined, the compiler might choose to not provide the non-expanded version at all. This requires that the function has internal linkage, and taking the address of the function typically makes such proof very difficult, or impossible.

like image 150
eerorika Avatar answered Oct 17 '22 06:10

eerorika


The inline keyword was originally a hint to the compiler that you the programmer think this function is a candidate for inlining - the compiler is not required to honor this.

In modern usage, it has little to nothing to do with inlining at all - modern compilers freely inline (or not) functions "behind you back", these form part of the optimization techniques.

Code transformations (including inlining) are done under the "as-if" rule in C++, which basically means that the compiler can transform the code as it wants to, so long as the execution is "as-if" the original code was executed as written. This rule fuels optimizations in C++.

That said, once an address is taken of a function, it is required to exist (i.e. the address is required to be valid). This may mean that it is no longer inlined, but could still be (the optimizer will apply the appropriate analysis).

So why can a pointer exist to a inline function, given that there is no fixed memory address of inline functions?

No, it is only a hint and largely relates to linkage and not actual inlining. This fuels, what is arguably the main current usage, defining functions in header files.

Should it not print different values of address of n each time func() is called?

It might, the n is a local variable, based on the stack location when the function executes. That said, the function inline, it relates to linkage, the linker will merge the functions over the translation units.


As noted in the comments;

... that if the example is changed to static int n, then every call to the function must print a constant value (in a single program run of course) ... and that is true whether or not the code is inlined or not.

This is, again, the effect of the linkage requirement on the local variable n.

like image 28
Niall Avatar answered Oct 17 '22 07:10

Niall