Const Reference to a Temporary Object

Take a look at the code snippet below:

1
2
3
4
5
6
7
8
9
10
struct Dog {
std::string name;
};

Dog CreateADog(std::string name) {
return Dog(name);
}

const Dog& new_dog = CreateADog("furball");
std::cout << "Introducing new dog: " << new_dog.name << std::endl;

What will happen if we try to compile it and run?

If you are not sure about the answer, read on.

If you know the answer already but don’t know why C++ behaves like this, read on.

Lifetime of a temporary object

In C++, the lifetime of a temporary object usually lasts till the end of the full expression. For example, in code snippet below:

1
Dog new_dog = CreateADog("snowball");

Function call CreateADog("snowball") will create a temporary Dog object and assign it to new_dog. The temporary object will be destroyed at the end of the expression, after the evaluation of the assignment operation.

Lifetime extension of a temporary object

There are some cases where the lifetime of a temporary object will be extended.

The case we will discuss today is when a const reference stack variable is bound to the temporary. In this case, the lifetime of the temporary object will be extended to the lifetime of the reference.

Recall the example from the beginning:

1
2
const Dog& new_dog = CreateADog("furball");
std::cout << "Introducing new dog: " << new_dog.name << std::endl;

This code will compile and print the name of the new dog. The lifetime of the temporary object created by CreateADog("furball") is extended, that’s why we can still access in the next expression.

Note ‘const’ keyword is necessary here. Otherwise the code won’t compile.

But why?

This might be a considering feature which silently helps programmers from crashing, but it is also counter-intuitive and may confuse people assuming temporary objects are destroyed at the end of the full-expression.

Why is this feature added? What benefit does it bring to the table? Will it justify the confusions it introduces?

This StackExchange thread answered the question by examining many original discussions and proposals.

TL;DR: The goal is to make the temporary object accessable through the reference, which is the reason why peopl
e will bind a reference originally.

This can actually be convenient sometimes, as illustrated in one of the proposals:

1
2
const substring & sr = (s + t).substr(1,5);  // << temporary!
cout << sr; // do need to store (s + t) explicitly

Reference