我一直想知道,字符串常量在 C++ 中存在多久。例如,如果我在函数内创建一些 const char *str = "something",返回 str 的值是否安全?
我编写了一个示例程序,并且非常惊讶地发现这样的返回值仍然存储了该字符串。这是代码:
#include <iostream>
using namespace std;
const char *func1()
{
const char *c = "I am a string too";
return c;
}
void func2(const char *c = "I'm a default string")
{
cout << c << endl;
}
const int *func3()
{
const int &b = 10;
return &b;
}
int main()
{
const char *c = "I'm a string";
cout << c << endl;
cout << func1() << endl;
func2();
func2("I'm not a default string");
cout << *func3() << endl;
return 0;
}
它给了我以下输出:
我是一根绳子
我也是一根绳子
我是默认字符串
我不是默认字符串
10
func3 的存在只是为了查明是否同样适用于其他类型。
所以问题是:返回指向该函数内创建的字符串常量的指针是否安全(如 func1() 中)?
另外,像 func2() 中那样使用默认字符串值是否安全?
字符串文字具有静态存储持续时间并持续程序的生命周期。来自C++标准草案部分
2.14.5
字符串文字段落8其中表示(强调我的前进):
也指普通字符串文字和UTF-8字符串文字 为窄字符串文字。窄字符串文字的类型为“array of n const char”,其中 n 是字符串的大小,定义如下, 并且 具有静态存储持续时间 (3.7)。
以及来自第
3.7.1
节静态存储持续时间第1段:
所有没有动态存储持续时间的变量,没有 线程存储持续时间,并且不是本地有静态存储 期间。 这些实体的存储应持续到 程序的说明(3.6.2、3.6.3)。
另一方面,
func3
中的第二种情况无效。临时绑定到引用的生命周期在引用的生命周期内持续存在,在本例中,引用在函数返回时结束。这在第12.2
节中有介绍,其中说:
第二个上下文是当引用绑定到临时对象时。115 引用绑定到的临时对象或作为引用的临时对象 引用绑定到的子对象的完整对象 在引用的生命周期内持续存在,除了:
func1中初始化的变量。
c是局部变量,它应该定义在堆栈上,我们看到它是使用$rbp中的堆栈地址放入堆栈的
0x00005555555551f1 <+8>: lea 0xe0c(%rip),%rax #0x555555556004
0x00005555555551f8 <+15>: mov %rax,-0x8(%rbp)
func1返回时,局部变量c将随func1的栈帧一起被销毁
c将使用寄存器$rax返回
0x00005555555551fc <+19>: mov -0x8(%rbp),%rax