Search code examples
c++inline-functions

Are the following inlined functions guaranteed to have the same implementation?


  • Are the following functions guaranteed to have the same implementation (i.e. object code)?
  • Does this change if Foo below is a primitive type instead (e.g. int)?
  • Does this change with the size of Foo?

Returning by value:

inline Foo getMyFooValue() { return myFoo; }

Foo foo = getMyFooValue();

Returning by reference:

inline const Foo &getMyFooReference() { return myFoo; }

Foo foo = getMyFooReference();

Modifying in place:

inline void getMyFooInPlace(Foo &theirFoo) { theirFoo = myFoo; }

Foo foo;
getMyFooInPlace(foo);

Solution

  • Are the following functions guaranteed to have the same implementation (i.e. object code)?

    No, the language only specifies behaviour, not code generation, so it's up to the compiler whether two pieces of code with equivalent behaviour produce the same object code.

    Does this change if Foo below is a primitive type instead (e.g. int)?

    If it is (or, more generally, if it's trivially copyable), then all three have the same behaviour, so can be expected to produce similar code.

    If it's a non-trivial class type, then it depends on what the class's special functions do. Each calls these functions in slightly different ways:

    • The first might copy-initialise a temporary object (calling the copy constructor), copy-initialise foo with that, then destroy the temporary (calling the destructor); but more likely it will elide the temporary, becoming equivalent to the second.
    • The second will copy-initialise foo (calling the copy constructor)
    • The third will default initialise foo (calling the default constructor), then copy-assign to it (calling the assignment operator).

    So whether or not they are equivalent depends on whether default-initialisation and copy-assignment has equivalent behaviour to copy-initialisation, and (perhaps) whether creating and destroying a temporary has side effects. If they are equivalent, then you'll probably get similar code.

    Does this change with the size of Foo?

    No the size is irrelevant. What matters is whether it's trivial (so that both copy initialisation and copy assignment simply copy bytes) or non-trivial (so that they call user-defined functions, which might or might not be equivalent to each other).