tags:

views:

200

answers:

4

Consider the following code where I am returning double& and a string&. The thing works fine in the case of a double but not in the case of a string. Why is this difference in the behavior?

In both the cases compiler does not even throws the Warning: returning address of local variable or temporary as I am returning a reference.

#include <iostream>
#include <string>
using namespace std;


double &getDouble(){
    double h = 46.5;
    double &refD = h;
    return refD;
}

string &getString(){
    string str = "Devil Jin";
    string &refStr = str;
    return refStr;
}

int main(){
    double d = getDouble();
    cout << "Double = " << d << endl;

    string str = getString();
    cout << "String = " << str.c_str() << endl;


    return 0;
}

Output:

$ ./a.exe
Double = 46.5
String =
+13  A: 

You should never return a reference to a local variable no matter what the compiler does or does not do. The compiler may be fooled easily. you should not base the correctness of your code on some warning which may not have fired.

The reason it didn't fire here is probably that you're not literally returning a reference to a local variable, you are returning a variable that is a reference to a local variable. The compiler probably doesn't detect this somewhat more complex situation. It only detects things like:

string &getString(){
    string str = "Devil Jin";
    return str;
}

The case of the double is simpler because it doesn't involve constructing and destructing a complex object so in this situation the flow control analysis of the compiler probably did a better job at detecting the mistake.

shoosh
local to the function, you obviously mean. you're allowed to return a reference to anything outside your scope: member data, function parameters taken as reference etc.
wilhelmtell
Actually, I think he says the warning is NOT fired even in the case of the double. So the compiler is fooled in both cases. The reason it works with the double is likely because the location of h on the stack has not been overwritten. Try this: in main store d in a double)
Philippe Beaudoin
+3  A: 

The reference to a double references an location that is still physically in memory though it is no longer be on the stack. You're only getting away with it because the memory hasn't been overwritten yet. Whereas the double is a primitive, the string is an object and has a destructor that may be "clearing" the internal string to a zero length when it falls out of scope. The fact that you aren't getting garbage from your call to c_str seems to support that.

Evan Huddleston
Honestly all this seems like speculation, and it really doesn't matter. When you return a reference to a local variable the compiler is allowed to do whatever it wants. If it feels like taking a break and going to the kitchen to make itself a sandwich then that is fine too by the standard. So the answer is simple: don't return a reference unless the variable isn't local to the function.
wilhelmtell
Which is why I said "getting away with it." I'm not supporting the behavior just trying to answer "why?"
Evan Huddleston
@wilhelmtell: It is not speculation, it is what will happen. The problem is once you use the return value, as all sorts of bad things can happen: the best thing to happen is your program segfaults; the worst is your program continues to work until it mysteriously misbehaves or segfaults later.
iconiK
Yes yes, I'm not criticizing your answer, just adding on top of it. Maybe I sounded like I do in my first sentence. :s
wilhelmtell
+1  A: 

GCC used to have an extension called Named Returns that let you accomplish the same thing, but allocated the space outside the function. Unfortunately it doesn't exist anymore; I'm not sure why they took it out

Michael Mrozek
Probably because it is not standard and the compiler does NRVO (Named Return Value Optimization) that will perform the same optimization with this code: `X foo() { X tmp; /* ... */; return tmp; }`. The compiler is able to do the same and be standard compliant at the same time. http://gcc.gnu.org/ml/gcc-help/2004-07/msg00054.html
David Rodríguez - dribeas
+1 for the historical reference, even if it is no longer valid. And welcome to SO.
David Rodríguez - dribeas
A: 

I had a similar post and the answers there were very helpful.

Also, check out the comments

http://stackoverflow.com/questions/2612709/why-does-this-object-wonk-out-get-deleted

brainydexter
Providing links to related questions or duplicates should be done via comments, not answers - especially if you are not adding any information.
Georg Fritzsche