perencia
perencia

Reputation: 1552

Why does "return string(...)" return a reference to a temporary?

I'm somewhat confused about the declaration of functions returning const references to temporaries.

In the following code

#include <string>
#include <iostream>

using namespace std;

const string& foo() { 
    return string("foo"); 
}
string bar() { 
    return string("bar"); 
}

int main() {
    const string& f = foo();
    const string& b = bar();
    cout << b;

}

What is the difference between methods foo and bar ?

Why does foo give me warning: returning reference to local temporary object [-Wreturn-stack-address]. Isn't a copy of the temporary created on const string& f = foo(); ?

Upvotes: 14

Views: 14152

Answers (4)

Andreas DM
Andreas DM

Reputation: 11028

Why does foo give me warning: returning reference to local temporary object [-Wreturn-stack-address].

You are creating a temporary string object inside foo(), and you are returning a reference to that object which will immediately go out of scope (dangling reference).

const string& foo() { 
    return string("foo"); // returns constant reference to temporary object
}                         // object goes out of scope

bar() is quite different:

string bar() {            
    return string("bar"); // returns a copy of temporary string
}
...
const string& b = bar();  // reference an rvalue string

What is the difference between methods foo and bar ?

foo() returns a constant (dangling) reference while bar() returns a copy of a temporary string object.

Upvotes: 4

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385405

Isn't a copy of the temporary created on const string& f = foo();

Where did you hear that?

Adding const to a reference often allows the lifetime of a temporary with which it's been initialised to be extended to the lifetime of the reference itself. There's never a copy.

Even that's not the case here, though. The object you're binding to the reference goes out of scope at the end of the function and that takes precedence over everything else.

You're returning a dangling reference; period.

Upvotes: 4

Mats Petersson
Mats Petersson

Reputation: 129524

string("foo") creates an object of type std::string containing the value "foo" locally in the function. This object will be destroyed at the end of the function. So returning the reference to that object will be invalid once the code leaves that function [1]. So in main, you will never have a valid reference to that string. The same would be true if you created a local variable inside foo.

The WHOLE point of returning a reference is that you don't make a copy, and initializing a reference (string &f = foo() is an initialization) will not create a copy of the original object - just another reference to the same object [which is already invalid by the time the code is back in main]. For many things, references can be seen as "a different name for the same thing".

The lifetime of the referred object (in other words, the actual object the "alias name" refers to) should ALWAYS have a lifetime longer than the reference variable (f in this case).

In the case of bar, the code will make a copy as part of the return string("bar");, since you are returning that object without taking its reference - in other words, by copying the object, so that works.

[1] pedantically, while still inside the function, but after the end of the code you have written within the function, in the bit of code the compiler introduced to deal with the destruction of objects created in the function.

Upvotes: 12

ibezito
ibezito

Reputation: 5822

In both of the cases, a string object is initialized and allocated on the stack. After returning from the function, the memory segment which contains it becomes irrelevant, and its content may be overridden.

The difference between the functions: bar function return a copy of the string instance which is created inside it.

foo function returns a reference to the string instance which is created inside it. In other words, it returns an implicit pointer to its return value, which resides in a temporary memory segment - and that's the reason for your warning.

Upvotes: 0

Related Questions