Home > Net >  In C what is the correct way to use the inline specifier?
In C what is the correct way to use the inline specifier?

Time:01-25

My goal is to reduce the function call overhead for some of the methods I have defined in my class. These methods are used by other methods and they are not intended to be publicly accessed. I have done some research but could not put together the information I found. Is it sufficient to specify the method inline in the definition and not in the declaration? Is it a bad technique if the method is publicly accessible?

file.h

class Foo
{
    /* ... */
public:
    bool bar ( int par );
    void zar ( void );
    /* ... */
};

file.cpp

inline bool Foo::bar ( int par )
{
    /* ... */
}

void Foo::zar ( void )
{
    /* ... */

    if ( bar(10) )
    {
        /* ... */
    }

    /* ... */
}

Is the usage of inline specifier in this example a good technique?

The code is operational but I want to understand the unforeseeable consequences. Whether this is the correct usage or not.

CodePudding user response:

inline has officially almost nothing to do with whether the function will be inlined or not.

Its official purpose is to allow multiple identical definitions to exist without violating the ODR (one-definition) rule. Meaning you can put the definition into a header, include it from multiple .cpp files - translation units - and the linker will not complain about multiple definitions, instead it will pick one. Therefore you must ensure the definitions are identical (i.e no two "unrelated" inline functions with the same name in separate .cpp files - they should have been marked static instead), otherwise good luck debugging the calls.

If you want to force inlining, there is no standard tool for that, but all compilers support directives to do so e.g. __attribute__((always_inline)) for g /clang.

But if you want to rely on the compiler to use its judgement, you can help it by ensuring the definition is available at the call site. This can be achived by either putting the definitions into headers or enabling link-time optimizations. The former means to put the definition inside the class or somewhere after the class definition, in that case mark them inline. Just note that this means that any change in the implementation will require recompilation of all translation units which include that header.

Is it sufficient to specify the method inline in the definition and not in the declaration? Is it a bad technique if the method is publicly accessible?

Not guaranteed but yes, if the compiler believes it is beneficial to inline the call, it has all the information necessary to do so. Bad technique? I would say that is completely orthogonal issue, caller should not care about the "calling convention". Make methods public based on API design alone.

Is the usage of inline specifier in this example a good technique?

No, it is useless to mark function inline inside a single translation unit. Because it is not visible to other units and it is already visible to the original unit. I would say that it is even dangerous to do so exactly due to my second paragraph, if someone else comes and implements inline Foo:bar in file2.cpp, the linker will silently most likely pick a single definition for all non-inlined calls but calls inside file.cpp which were inlined will call file::bar definition - as I said, good luck tracking those issues.

CodePudding user response:

inline is mostly a historical artifact similar to register, a recommendation to the compiler from a time when compilers were too dumb to make the call what to inline and when (1990s - early 2000s).

From 7.1.2:

The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism.

Nowadays, there is nearly no valid situation where you should be using it, save for some special cases of manual optimization and such. In general, you shouldn't be using it at all.

It's an optimization for execution speed over program size. Historically you would use inline for small functions to reduce the function call overhead. People had this nasty habit of using function-like macros for that purpose and inline was supposed to put a stop to that.

For inline to work as expected, the function definition needs to be in the same translation unit (.cpp file and all headers it includes) as the caller. Which typically means that it needs to be placed in a header. It's not necessarily a bad ting to inline public methods, particularly simple setters/getters, but you shouldn't need to.


EDIT:

Note that inline should be accompanied with static to ensure that multiple definitions of the function aren't possible. This is required for the one definition rule (7.1.2):

An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions defined by 7.1.2 shall still be respected.

An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case

An inline function shall be defined in every translation unit in which it is odr-used.

(Similarly in C, if you declare an inline function without static and don't define the function in the same translation unit, you invoke undefined behavior (6.7.4/7).)

CodePudding user response:

In C , the inline specifier can be used to indicate that a function should be inlined. To use the inline specifier, place the keyword "inline" before the function definition, like this:

inline int add(int a, int b) {
  return a   b;
}

It is important to note that use of inline keyword is a request to the compiler to insert the code of a function at the point where the function is called. Compiler has the freedom to ignore the request, mainly to prevent code bloat.

Additionally, inline functions should be defined in a header file, and should be defined only once across all translation units that include that header file. This is because when a function is inlined, its code is copied into each location where the function is called, which can cause multiple definition errors if the function is defined in multiple translation units.

  • Related