Sean Latham
Sean Latham

Reputation: 250

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

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);

Upvotes: 1

Views: 60

Answers (2)

Mike Seymour
Mike Seymour

Reputation: 254761

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).

Upvotes: 1

Peter - Reinstate Monica
Peter - Reinstate Monica

Reputation: 16112

The standard draft N3337 contains the following rules in 1.9.5: "A conforming [C++] implementation [...] shall produce the same observable behaviour as one of the possible executions of the corresponding instance of the abstract machine with the same program and the same input." And in 1.9.9 it defines the observable behaviour basically as I/O and volatile's values. Which means that as long as the I/O and volatiles of your program stay the same the implementation can do what it wants. If you have no I/O or volatiles the program doesn't need to do anything (which makes benchmarks hard to get right with high optimizations).

Note that the standard specifically is totally silent about what code a compiler should emit. Hell, it could probably interpret the sources.

This answers your question: No.

Upvotes: 0

Related Questions