2011-09-21 77 views
2

为什么此代码可以在Code :: block中成功运行。美洲开发银行刚刚报道返回对本地变量的引用

警告: “参照局部变量‘TMP’返回”,

但输出中的结果 “Hello World” 的成功。

#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; 
} 
+1

[返回局部或临时变量的地址]的可能重复(http://stackoverflow.com/questions/2744264/returning-the-address-of-local-or-temporary-variable) – iammilind

回答

1

您正在导致未定义的行为。该标准并没有说明在这种情况下会发生什么,然而你的编译器检测到它。

2

在离开函数时,所有局部变量都被销毁。通过返回对tmp的引用,您将返回对即将不复存在的对象的引用(即从技术上说,内存区域的内容不再有意义的地址)。

访问这样的悬挂引用调用所谓的'未定义行为' - 可悲的是,'照常工作'是一种'未定义的行为'。这里可能发生的情况是std::string为小字符串保留了一个小的静态缓冲区(与大字符串相反,为此它从堆中获取内存),并且在离开getString时,此字符串占用的堆栈空间未被清零,因此它似乎仍然上班。

如果您尝试调试构建,或调用其中一个函数(这将有效覆盖堆栈空间),它将不再工作。

+0

公寓添加**不要这样做**并且不要依赖编译器会在某些情况下返回给您有效的字符串,为此您可能会发现它可以正常工作,但不能保证它能在下次使用。 –

1

tmp在您从getString返回的那一刻消失。使用返回的引用是未定义的行为,所以任何事情都可能发生。

要修复您的代码,返回值的字符串:

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

你确定吗?它应该segfault(它将在大多数平台上与gcc)。该代码确实包含错误,如果您获得“幸运”并且它有效,那么您正在刷下地毯下的一个令人讨厌的错误。

您的字符串是通过引用返回的,也就是说,不是在返回的上下文中创建一个有效的新字符串,而是返回一个陈旧的,被销毁的对象的指针,这是不好的。 const string getString...将作为函数返回类型的声明。

0

临时对象被释放,但是它的内容仍然在堆栈中,直到重写它为止。尝试调用调用你的函数,并打印出返回的对象之间的一些功能:

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

C++标准告诉一个临时对象绑定到一个常量引用的临时的寿命延长到基准本身的寿命。因此,代码应该适用于任何符合标准的编译器,但在我看来,这种做法本身并不是很好。

如果你在你的例子中使用了一个当前未使用的字符串作为字符串a = getString(“Hello World!”),你只需制作一个副本,如果是const字符串& a = getString(“Hello World! “)我敢打赌,你永远不应该有你的临时垃圾。

0

正如你所看到的,通过调用goodByeString()稍微修改下面的示例代码。像其他答案一样,已经指出,名为tmp的getString中的变量是本地的。只要函数返回,变量就会超出范围。因为它是堆栈分配的,所以当函数返回时内存仍然有效,但是一旦堆栈再次增长,tmp驻留的这部分内存就会被别的东西重写。然后,对a的引用包含垃圾。

但是,如果您决定输出b,因为它不是通过引用返回,则内容仍然有效。

#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; 
}