[9] Inline functions
(Part of C++ FAQ Lite, Copyright © 1991-2001, Marshall Cline, cline@parashift.com)


FAQs in section [9]:


[9.1] What's the deal with inline functions?

An inline function is a function whose code gets inserted into the caller's code stream. Like a #define macro, inline functions improve performance by avoiding the overhead of the call itself and (especially!) by the compiler being able to optimize through the call ("procedural integration").

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[9.2] How can inline functions help with the tradeoff of safety vs. speed?

In straight C, you can achieve "encapsulated structs" by putting a void* in a struct, in which case the void* points to the real data that is unknown to users of the struct. Therefore users of the struct don't know how to interpret the stuff pointed to by the void*, but the access functions cast the void* to the approprate hidden type. This gives a form of encapsulation.

Unfortunately it forfeits type safety, and also imposes a function call to access even trivial fields of the struct (if you allowed direct access to the struct's fields, anyone and everyone would be able to get direct access since they would of necessity know how to interpret the stuff pointed to by the void*; this would make it difficult to change the underlying data structure).

Function call overhead is small, but can add up. C++ classes allow function calls to be expanded inline. This lets you have the safety of encapsulation along with the speed of direct access. Furthermore the parameter types of these inline functions are checked by the compiler, an improvement over C's #define macros.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[9.3] Why should I use inline functions? Why not just use plain old #define macros?

Because #define macros are evil in 4 different ways: evil#1, evil#2, evil#3, and evil#4.

Unlike #define macros, inline functions avoid infamous macro errors since inline functions always evaluate every argument exactly once. In other words, invoking an inline function is semantically just like invoking a regular function, only faster:

 // A macro that returns the absolute value of i
 #define unsafe(i)  \
         ( (i) >= 0 ? (i) : -(i) )
 
 
// An inline function that returns the absolute value of i
 inline
 int safe(int i)
 {
   return i >= 0 ? i : -i;
 }
 
 int f();
 
 void userCode(int x)
 {
   int ans;
 
   ans = unsafe(x++);   
// Error! x is incremented twice
   ans = unsafe(f());   
// Danger! f() is called twice
 
   ans = safe(x++);     
// Correct! x is incremented once
   ans = safe(f());     
// Correct! f() is called once
 }

Also unlike macros, argument types are checked, and necessary conversions are performed correctly.

Macros are bad for your health; don't use them unless you have to.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[9.4] How do you tell the compiler to make a non-member function inline?

When you declare an inline function, it looks just like a normal function:

 void f(int i, char c);

But when you define an inline function, you prepend the function's definition with the keyword inline, and you put the definition into a header file:

 inline
 void f(int i, char c)
 {
   
// ...
 }

Note: It's imperative that the function's definition (the part between the {...}) be placed in a header file, unless the function is used only in a single .cpp file. In particular, if you put the inline function's definition into a .cpp file and you call it from some other .cpp file, you'll get an "unresolved external" error from the linker.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[9.5] How do you tell the compiler to make a member function inline?

When you declare an inline member function, it looks just like a normal member function:

 class Fred {
 public:
   void f(int i, char c);
 };

But when you define an inline member function, you prepend the member function's definition with the keyword inline, and you put the definition into a header file:

 inline
 void Fred::f(int i, char c)
 {
   
// ...
 }

It's usually imperative that the function's definition (the part between the {...}) be placed in a header file. If you put the inline function's definition into a .cpp file, and if it is called from some other .cpp file, you'll get an "unresolved external" error from the linker.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[9.6] Is there another way to tell the compiler to make a member function inline?

Yep: define the member function in the class body itself:

 class Fred {
 public:
   void f(int i, char c)
     {
       
// ...
     }
 };

Although this is easier on the person who writes the class, it's harder on all the readers since it mixes "what" a class does with "how" it does them. Because of this mixture, we normally prefer to define member functions outside the class body with the inline keyword. The insight that makes sense of this: in a reuse-oriented world, there will usually be many people who use your class, but there is only one person who builds it (yourself); therefore you should do things that favor the many rather than the few.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[9.7] Are inline functions guaranteed to make your performance better? UPDATED!

[Recently explained "code bloat" and also added lots of if's, and's and but's (in 4/01). Click here to go to the next FAQ in the "chain" of recent changes.]

Nope.

Beware that overuse of inline functions can cause code bloat, which can in turn have a negative performance impact in paging environments.

The term code bloat simply means that the size of the code gets larger (bloated). In the context of inline functions, the concern is that too many inline functions might increase the size of the executable (i.e., cause code bloat), and that might cause the operating system to thrash, which simply means it spends most of its time going out to disk to pull in the next chunk of code.

Of course it's also possible that inline functions will decrease the size of the executable. This may seem backwards, but it's really true. In particular, the amount of code necessary to call a function is sometimes greater than the amount of code to expand the function inline. This can happen with very short functions, and it can also happen with long functions when the optimizer is able to remove a lot of redundant code — that is, when the optimizer is able to make the long function short.

So the message is this: there is no simple answer. You have to play with it to see what is best. Do not settle for a simplistic answer like, "Never use inline functions" or "Always use inline functions" or "Use inline functions if and only if the function is less than N lines of code." These one-size-fits-all rules may be easy to use, but they will produce sub-optimal results.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


E-Mail E-mail the author
C++ FAQ LiteTable of contentsSubject indexAbout the author©Download your own copy ]
Revised Aug 15, 2001