Matthias Matthias - 9 days ago 4
C++ Question

In C++ when can one return a class instance?

I am reading a Java to C++ crash course, beside others it talks about memory management in C++. An example is given to show what must not be done:

Foo& FooFactory::createBadFoo(int a, int b)
{
Foo aLocalFooInstance(a, b); // creates a local instance of the class Foo
return aLocalFooInstance; // returns a reference to this instance
}


This would not work because
aLocalFooInstance
leaves scope and is destroyed. Fine, makes sense to me. Now as one solution to this problem the following code is given:

Foo FooFactory::createFoo(int a, int b)
{
return Foo(a, b); // returns an instance of Foo
}


What I don't understand: why is the second example valid C++ code? Is the basic issue not the same in both examples, that is, that an instance of
Foo
is created, which would go out of scope and is thus destroyed when we return from the method?

Answer

Say we have the code

Foo FooFactory::createFoo(int a, int b) 
{
    return Foo(a, b);  // returns an instance of Foo
}

int main() {
    Foo foo = FooFactory::createFoo(0, 0);
}

It is important to distinguish between the various Foo objects created.

Conceptually, execution proceeds as follows:

  1. When the expression Foo(a, b) in the return statement is evaluated, a temporary object of type Foo is created.
  2. After the expression in the return statement has been evaluated, the return value itself is initialized from that expression. This results in the creation of another temporary of type Foo.
  3. The temporary created in step 1 is destroyed.
  4. The temporary created in step 2 is the result of the function call expression FooFactory::createFoo(0, 0) in the calling function. That temporary is used to initialize the non-temporary object foo.
  5. The temporary created in step 2 is destroyed.

In the presence of copy elision and return value optimization, it is possible for both temporaries to be elided.

Note that if the function returns by reference, then step 2 does not create a new object; it only creates a reference. Hence, after step 3, the object referred to does not exist anymore, and in step 4, the initialization will occur from a dangling reference.

Comments