[9] Inline functions
(Part of C++ FAQ Lite, Copyright © 1991-2000, 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 section ]


[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 section ]


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

[Recently added cross references to other evilness of macros (on 3/00) and rewrote the sentence on #define being evil (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]

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 section ]


[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 section ]


[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 section ]


[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 section ]


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

Nope.

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

TopBottomPrevious sectionNext section ]


E-Mail E-mail the author
C++ FAQ LiteTable of contentsSubject indexAbout the author©Download your own copy ]
Revised Jul 10, 2000