C++ 中的引用和字面量

reference and literals in C++

我知道 "literals"(c 字符串、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 returns 对文字的 const 引用 (2) 为什么这会导致崩溃? foo() 的栈中存储的是整数 2 吗?

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

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

第一种情况:

const int& foo()
{
    return 2;
}

return 语句创建了一个 临时对象 ,它是文字 2 副本 。所以它的地址要么是 non-extant 要么不同于文字 2 的位置(假设文字 2 有一个位置 - 不保证)。

就是那个引用为 returned.

的临时文件

第二种情况:

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

return 语句创建了一个 临时对象 ,它是 指针 [=] 的 副本 44=] 到文字 char 数组的 第一个元素 地址 指针 包含文字数组的实际地址,并且该地址是 returned 通过复制 给调用者。

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

这确实非常令人困惑,为了理解发生了什么,必须深入研究语言规范。

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

In function 'const int& foo()': 3 : warning: returning reference to temporary [-Wreturn-local-addr] return 2; ^

现在,您的第一个示例发生了什么?不能真正获取整数文字的地址,因为它们并不真正作为对象存在。但是,允许将常量引用绑定到文字。当每个人都知道引用类似于指针时,这怎么可能呢?原因是当您将 const 引用绑定到文字时,您并没有真正将它绑定到文字。相反,编译器会创建一个临时变量,并将您的引用绑定到它。该变量是一个对象,尽管是短暂的。一旦你运行returns,临时对象被销毁,你最终得到悬空引用->崩溃。

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