C++: Inline Functions

Even though overuse of getter and setter functions can be frowned upon, they can help a lot if you’re looking to provide a intuitive api. However the overhead the additional function call introduces is undesirable. Thankfully, there’s the inline keyword. It tells the compiler to replace each invocation of the function with the body of the function.

struct Foo {
  int m_number = 123;

  inline int number () {
    return m_number;
  }
};

int main () {
  Foo foo;

  // used like a regular function
  std::cout << foo.number() << std::endl;

  // compiled to almost identical assembly as this
  std::cout << foo.m_number << std::endl;

  return 0;
}

However the inline keyword isn’t a guarantee that the compiler will do this. It’s more of a hint to the compiler. So keep in mind that the compiler is free to ignore the fact that a function is declared inline and it can inline functions that haven’t been delcared as such. But in examples similar to the one above, you can assume it will behave as expected.

Another important piece of information is that the function definition needs to be available in every translation unit.

// foo.h
inline int foo ();
// foo.cpp
#include "foo.h"

int foo () {
  return 123;
}

If I try to use the foo function by including foo.h I’d get a warning telling me that the foo is not defined. This won’t prevent compilation, but the function will not get inlined. The compiler needs access to the function body to replace it with the call site. There’s a simple solution though. Just put the function definition in the header.

// foo.h
inline int foo () {
  return 123;
}

One finall note. Using inline too much can not only make your binary much bigger, but it can also slow it down due to the way things are cached during execution. So only use them on very small functions (1-3 lines) and you should be good.