考虑以下代码,我将返回double&
和string&
。它在双精度的情况下工作正常,但在字符串的情况下则不行。为什么行为不同?
在两个的情况下,编译器甚至不会抛出Warning: returning address of local variable or temporary
,因为我正在返回引用。
#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;
}
输出:
$ ./a.exe
Double = 46.5
String =
答案 0 :(得分:16)
无论编译器做什么或不做什么,都不应该返回对局部变量的引用。编译器可能很容易被欺骗。你不应该将你的代码的正确性建立在一些可能没有被解雇的警告上。
这里没有触发的原因可能是你没有真正返回对局部变量的引用,而是返回一个对局部变量的引用的变量。编译器可能没有检测到这种更复杂的情况。它只检测如下内容:
string &getString(){
string str = "Devil Jin";
return str;
}
double的情况比较简单,因为它不涉及构造和破坏复杂对象,因此在这种情况下,编译器的流控制分析可能在检测错误方面做得更好。
答案 1 :(得分:6)
对double
的引用是指仍然在物理上在内存但不再在堆栈中的位置。你只是逃避它,因为内存还没有被覆盖。 double
是一个原语,string
是一个对象,并且有一个析构函数,当它超出范围时,可以将内部字符串清零为零长度。您拨打c_str()
时没有收到垃圾的事实似乎支持这一点。
答案 2 :(得分:1)
GCC曾经有一个名为Named Returns的扩展程序,它允许您完成同样的事情,但是在函数外部分配了空间。不幸的是它不再存在了;我不确定他们为什么把它拿出来
答案 3 :(得分:0)
关于C ++的Dangling引用的经典案例。双变量不在调用堆栈上,而返回引用试图访问它,调用编译器来设置防护标志。但是,String具有显式的垃圾收集机制,使您的编译器可以忽略该场景。