开发者

Returning reference to a local variable

开发者 https://www.devze.com 2023-04-06 22:37 出处:网络
Why can this code run successfully in Code::block. The IDB just reports warning: \"reference to local variable ‘tmp’ returned\",

Why can this code run successfully in Code::block. The IDB just reports

warning: "reference to local variable ‘tmp’ returned",

but ouput the result "hello world" successfully.

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

const string &getString(const string &s)
{
 开发者_运维技巧   string tmp = s;
    return tmp;
}

int main()
{
    string a;
    cout<<getString("hello world")<<endl;
    return 0;
}


Upon leaving a function, all local variables are destroyed. By returning a reference to tmp, you are returning a reference to an object that soon ceases to exist (that is, technically, the address of a memory region whose contents are no longer meaningful).

Accessing such a dangling reference invokes what is called 'undefined behaviour' - and sadly, 'work as usual' is one kind of 'undefined behaviour'. What might happen here is that std::string keeps a small static buffer for small strings (as opposed to large strings, for which it grabs memory from the heap), and upon leaving getString the stack space occupied by this string is not zeroed so it still seems to work.

If you try a debug build, or invoke another function in between (which will effectively overwrite the stack space), it won't work anymore.


You are causing an undefined behaviour. The standard doesn't tell what happens in that case, however your compiler detected it.


tmp disappears the moment you return from getString. Using the returned reference is undefined behaviour, so anything can happen.

To fix your code, return the string by value:

string getString(const string &s)
{
...


Are you sure? It should segfault (it will with gcc on most platforms). That code does contain an error, and if you get 'lucky' and it works, then you're brushing a nasty bug under the carpet.

Your string is returned by reference, that is, rather than making a new string which is valid in the context you are returning into, a pointer to a stale, destructed, object is being returned, which is bad. const string getString... will do as the declaration for the function's return type.


The temporary object is deallocated, however its contents are still there on the stack, until something rewrites it. Try to call a few functions between calling your function and printing out the returned object:

const string& garbage = getString("Hello World!");
callSomeFunctionThatUsesALotOfStackMemory();
cout<< garbage << endl;


As you can see the below example code is just slightly modified by calling goodByeString(). Like the other answers already pointed out the variable in getString called tmp is local. the variable gets out of scope as soon as the function returns. since it is stack allocated the memory is still valid when the function returns, but as soon as the stack grows again this portion of memory where tmp resided gets rewritten with something else. Then the reference to a contains garbage.

However if you decide to output b since it isn't returned by reference the contents is still valid.

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

const string &getString(const string &s)
{
  string tmp = s;
  return tmp;
}

string goodByeString(const string &s)
{
  string tmp = "lala";
  tmp += s;
  return tmp;
}

int main()
{
   const string &a = getString("Hello World!\n");
   string b = goodByeString("ciao\n");
   cout << a << endl;
   return 0;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号