c++ 字符串文字的静态分配是否适用于任何 const char *

c++ does static allocation of string literals apply to any const char *

在 Stroustrup C++ 4thEd p176 中,他声明此代码是安全的,因为字符串文字是静态分配的

const char∗ f() { return "some literal"; }

我有两个问题:

首先,在哪个 C++ 修订版中出现了这种情况? (它是否依赖于实现?)

其次,这会扩展到任何 "const char*" 吗? 在第二部分,我想答案是否定的,因为这导致了 运行 时间错误:

const char* make_const_char_ptr(){ 
    const char res [] = {'a','b','c', '[=11=]' }; 
    return res; 
}

First, at which revision of C++ did that became the case?

自 C++ 标准化以来一直如此。字符串文字具有静态 storage duration.

Second, does this extend to any "const char*" ?

是的,如果您返回的对象具有静态存储。但在您的示例中并非如此。 res 具有自动存储期限。相反,您可以这样做:

const char* make_const_char_ptr() { 
    static const char res [] = { 'a', 'b', 'c', '[=10=]' }; 
    return res; 
}

有效。

对于 return 函数的具有自动存储持续时间的变量的引用或指针会调用未定义的行为,因为在退出函数后,引用或指向的变量将不存在。

字符串文字具有静态存储持续时间,因此您可以 return 一个指针或对字符串文字的引用。

您还可以 return 引用或指针指向使用存储说明符 static 声明的函数局部变量。

例如使用这个函数定义

const char* make_const_char_ptr(){ 
    const char res [] = {'a','b','c', '[=10=]' }; 
    return res; 
}

这段代码

const char *s = make_const_char_ptr();
size_t n = strlen( s );

调用未定义的行为,因为存储在数组 res 中的具有自动存储持续时间的指向字符串将不存在。

但是如果函数定义如下

const char* make_const_char_ptr(){ 
    const static char res [] = {'a','b','c', '[=12=]' }; 
    return res; 
}

然后这个代码片段

const char *s = make_const_char_ptr();
size_t n = strlen( s );

是正确的,因为数组 res 仍然存在。在这种情况下,限定符 const 无关紧要。即不影响数组的生命周期。

注意数组的初始化方式并不重要:是使用字符串文字还是字符的初始化列表。

函数内的声明

const char res [] = { "abc" }; 

如果存储说明符 static 不存在,则具有自动存储持续时间。

下面是一个演示程序,其中字符串文字是通过引用从函数中 return 编辑的。

#include <iostream>
#include <type_traits>

decltype( auto ) f()
{
    return ( "hello World" );
}

void g( const char *s )
{
    std::cout << s << '\n';
}

int main() 
{
    decltype( auto ) s = f();

    g( s );

    std::cout << std::extent<std::remove_reference<decltype( s )>::type>::value << '\n';

    return 0;
}

程序输出为

hello World
12

该语句指的是文字而不是任何 const char*,您必须注意 const char* 和文字之间的区别。 你提到的第一行代码:

const char∗ f() { return "some literal"; } 

包含文字 "some literal" 编译器通过静态分配表示的字符串来解释它。 另一段代码:

const char* make_const_char_ptr(){ 
    const static char res [] = {'a','b','c', '[=11=]' }; 
    return res; 
}

被解释为分配一个 char 数组,然后 return 指向该数组开头的指针,但是一旦程序 return 来自函数的数组被释放(因此不再访问 returning 值指向的地址是不安全的。return 的类型对于两个函数都是相同的,但在第一种情况下链接到文字(静态分配,而不是在 return 上销毁)在另一种情况下,您告诉编译器分配一个范围限于函数本身的数组(与文字的静态情况相反)。