By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,203 Members | 1,383 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,203 IT Pros & Developers. It's quick & easy.

Returning reference to local variable - is this okay?

P: 1
Hi, I have tried to find an answer to the this question on the internet but can't. The compiler gives a warning, but this program works okay.

Expand|Select|Wrap|Line Numbers
  1. int &f()
  2. {
  3.     int c=4;
  4.     return c;
  5. }
  6. int main()
  7. {
  8.     int b=f();
  9.     cout<<b;
  10. }
Is there anything bad about this, or is this a disaster waiting to happen? I think it depends on whether variable c is still in existence when the return was made. One book I was reading said that all function variables except the return variable were destroyed BEFORE the return was made, in that case this program shouldn't work - or should it???? Thankyou in advance.
Aug 6 '07 #1
Share this Question
Share on Google+
9 Replies


RedSon
Expert 5K+
P: 5,000
Hi, I have tried to find an answer to the this question on the internet but can't. The compiler gives a warning, but this program works okay.

Expand|Select|Wrap|Line Numbers
  1. int &f()
  2. {
  3.     int c=4;
  4.     return c;
  5. }
  6. int main()
  7. {
  8.     int b=f();
  9.     cout<<b;
  10. }
Is there anything bad about this, or is this a disaster waiting to happen? I think it depends on whether variable c is still in existence when the return was made. One book I was reading said that all function variables except the return variable were destroyed BEFORE the return was made, in that case this program shouldn't work - or should it???? Thankyou in advance.
Why is your method signature &f() ?
Aug 6 '07 #2

P: 19
Good question... Did you mean "int& f()", that is a whole different thing for the brain-based parser.

That aside, I'd say the answer to the "a disaster waiting to happen" question is "definitely yeah". When the function returns int&, it returns not the value of c, but the reference of c; since c is declared locally, it's also destroyed when it goes out of scope, as expected. So now you are indeed returning a pointer to an unallocated memory zone. In this situation, two things might happen:
  1. The call to f and the actual use of the return value (which, I stress again, is a reference and not the actual content of the referenced variable) are very close to each other, time wise; the memory zone previously used by the call to f is still untouched. As such, the old value of c is at the proper place and it can be read in main. That's why the program works.
  2. The call to f and the actual use of the return value are a long time from each other. With this, the probabilities increase that somebody else has claimed that particular bit of free memory, and the contents of the old &c are no longer there; but the calling code doesn't know that, so it just goes on.
And that's the gist of it. The program might function perfectly, might cause a fatal error, it might work without a glitch and cause sudden death 5 instructions later, or whatever else fancies it. It all depends on exactly what data overwrote the old c. In Jargon file parlance, this would be a heisenbug...
Aug 6 '07 #3

Expert 10K+
P: 11,448
Hi, I have tried to find an answer to the this question on the internet but can't. The compiler gives a warning, but this program works okay.

Expand|Select|Wrap|Line Numbers
  1. int &f()
  2. {
  3.     int c=4;
  4.     return c;
  5. }
  6. int main()
  7. {
  8.     int b=f();
  9.     cout<<b;
  10. }
Is there anything bad about this, or is this a disaster waiting to happen? I think it depends on whether variable c is still in existence when the return was made. One book I was reading said that all function variables except the return variable were destroyed BEFORE the return was made, in that case this program shouldn't work - or should it???? Thankyou in advance.
Yes it's bad; very bad, because local variables cease to exist after the function
returned and you pass a reference back to something that doesn't exist anymore.
It's just undefined behaviour according to the Standard. In other words: bad.

kind regards,

Jos
Aug 6 '07 #4

P: 86
It's undefined behavior and not guaranteed to work.

The fact is that the reference is pointing somewhere, and that somewhere can be output and in a trivial program like your example that somewhere is likely to be equal to the same thing it was when used... But there's nothing protecting that somewhere from getting overwritten later in your program which in a larger program would more likely happen and then you'd have problems.
Aug 6 '07 #5

P: 14
Sorry this post is somewhat old but I have the same question. I understand why this is problematic. However I am uncertain how to do this better.

Expand|Select|Wrap|Line Numbers
  1. int & f()
  2. {
  3.    int c=4;
  4.    return c;
  5. }
  6. int main()
  7. {
  8.     int b=f();
  9.     cout<<b;
  10. }
I think that I can do this however I am not sure what the implications would be:

Expand|Select|Wrap|Line Numbers
  1. int & f()
  2. {
  3.    int c = new int(4);
  4.    return c;
  5. }
  6. int main()
  7. {
  8.     int b=f();
  9.     cout<<b;
  10. }
I think that this creates the new variable c on the system heap as oposed to the stack. I think that c will never go away unless the user explicitly tells c to die. (I think that there is a free keyword or something that releases things that where created with new).
Nov 14 '08 #6

P: 17
For your example, the best thing is probably to return by value directly (i.e "int f()"), since we are dealing with simple data types, which are cheap to copy.

For larger data types, you have to choose between copying or allocating dynamically. Dynamic memory gets tricky since you need to delete it when it is no longer used. The general recommendation is to use classes (constructors and destructors) to manage this. This idiom is called RAII. With this approach, you only use "new" or "delete" within constructors and destructors (naturally with some exceptions).
Nov 14 '08 #7

Expert 100+
P: 2,400
I think that this creates the new variable c on the system heap as opposed to the stack. I think that c will never go away unless the user explicitly tells c to die. (I think that there is a free keyword or something that releases things that where created with new).
So ... you're hoping that by making c a persistent variable you'll avoid undefined behavior. Sometimes that's exactly the right thing to do: when the purpose of your function is to create an instance of some type. Is that what your function is for?

If all you're doing is allocating a persistent variable so you can return a value then you're going through a lot of trouble risking undefined behavior to do something that could be accomplished much easier by changing the function to return an int rather than the address of an int.

As for your immediate question, I don't know if your proposed syntax will actually create a persistent variable.
Nov 14 '08 #8

P: 17
I also don't think there is any way in C++ to pass a reference to a function, and then construct a variable directly into that memory space, thus you may not fiddle with the callers stack (maybe someone knows more about this?).

Also see return by value faq
Nov 14 '08 #9

Savage
Expert 100+
P: 1,764
You could always try using static.

Expand|Select|Wrap|Line Numbers
  1. int & f()
  2. {
  3.    static int c = new int(4);
  4.    return c;
  5. }
  6. int main()
  7. {
  8.     int b=f();
  9.     cout<<b;
  10. }
Nov 14 '08 #10

Post your reply

Sign in to post your reply or Sign up for a free account.