C ++中的引用和文字

时间:2016-10-14 17:07:09

标签: c++ rvalue

我知道"文字" (c strings,int或者其他)存储在某个地方(显然只读数据部分.rodata)也许这不准确...

我想了解为什么此代码会导致运行时错误:

#include <iostream>
using namespace std;

const int& foo()
{
    return 2;
}
const char* bar()
{
    return "Hello !";
}

int main() {

    cout << foo() << endl; // crash

    cout << bar() << endl; // OK

    return 0;
}

foo返回一个文字的const引用(2)为什么会导致崩溃?是存储在foo()?

堆栈中的整数2

另请参阅:Why are string literals l-value while all other literals are r-value?

2 个答案:

答案 0 :(得分:5)

我明白为什么这会让人感到困惑,所以我会尝试将其分解。

第一种情况:

const int& foo()
{
    return 2;
}

return语句创建一个临时对象,它是文字2副本。因此,它的地址要么非现存,要么与文字2的位置不同(假设文字2有位置 - 无法保证)。

这是临时的,其参考被返回。

第二种情况:

const char* bar()
{
    return "Hello !";
}

return语句将临时对象作为指针副本地址 文字字符数组的第一个元素指针包含文字数组的实际地址,该地址通过复制返回给调用者。

总结一下。第二个是有效的,因为return语句需要文本地址的副本,而不是文字本身的副本。 地址的存储是暂时的并不重要,因为地址在暂时保持其值崩溃后仍然指向正确的位置。

答案 1 :(得分:3)

这确实非常令人困惑,为了理解正在发生的事情,我们必须深入研究语言规范。

但在我们这样做之前,请允许我提醒您编译器警告是您的朋友。如果有足够的警告级别,您应该在编译示例时看到以下内容:

  

在函数'const int&amp; foo()':3:警告:返回引用   临时[-Wreturn-local-addr]返回2; ^

现在,您的第一个例子中发生了什么?人们不能真正获取积分文字的地址,因为它们并不真正作为对象存在。但是,允许一个绑定文字的常量引用。当每个人都知道引用类似于指针时,怎么可能呢?原因是当你将const引用绑定到文字时,你并没有真正将它绑定到文字。相反,编译器会创建一个临时变量,并将您的引用绑定到它。而这个变量是一个对象,虽然是短暂的。一旦你的函数返回,临时对象就会被破坏,你最终会得到悬空参考 - &gt;崩溃。

在第二个示例中,"hello"是一个文字,但您没有返回文字 - 您正在返回指向该字符串的指针。并且指针保持有效,因为它指向的字符串保持有效。