为什么 C++ 中的字符串文字 (char*) 必须是常量?

Ser*_*ket 44 c c++ pointers string-literals

我最近一直在学习 C++ 并意识到 C++ 中的字符串文字必须是常量,而在 C 中,它们不是。这是一个例子。以下代码在 C 中有效,但在 C++ 中无效:

char* str = "Hello World";
Run Code Online (Sandbox Code Playgroud)

为了在 C++ 中做同样的事情,必须使用以下语句:

const char* str = "Hello World";
Run Code Online (Sandbox Code Playgroud)

有人可以解释为什么吗?

Joh*_*ode 38

稍微扩展一下 Christian Gibbons 的回答……

在 C 中,像这样的字符串文字"Hello World"存储在数组中,char这样它们在程序的生命周期内都是可见的。字符串文字应该是不可变的,一些实现会将它们存储在只读内存段中(这样尝试修改文字的内容将触发运行时错误)。一些实现不会,并且尝试修改文字的内容可能不会触发运行时错误(它甚至可能看起来像预期的那样工作)。C 语言定义将行为保留为“未定义”,以便编译器可以自由地处理它认为合适的情况。

在 C++ 中,字符串文字存储在 的数组中const char,因此任何修改文字内容的尝试都将在编译时触发诊断。

正如 Christian 指出的那样,const关键字最初不是 C 的一部分。然而,它最初是 C++ 的一部分,这使得使用字符串文字更安全一些。

请记住,const关键字并不表示“将其存储在只读内存中”,它仅表示“这件事可能不是赋值的目标”。

还请记住,除非它是sizeof或 一元运算*符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则“N 元素数组”类型的表达式T将被转换(“衰减”)为“指向T”类型的表达式,表达式的值将是数组第一个元素的地址。

在 C++ 中,当你写

const char *str = "Hello, world";
Run Code Online (Sandbox Code Playgroud)

字符串的第一个字符的地址存储到str. 您可以设置str指向不同的字符串文字:

str = "Goodbye cruel world";
Run Code Online (Sandbox Code Playgroud)

但是你不能做的是修改字符串的内容,比如

str[0] = 'h';
Run Code Online (Sandbox Code Playgroud)

或者

strcpy( str, "Something else" );
Run Code Online (Sandbox Code Playgroud)


Chr*_*ons 25

C 最初没有const关键字,因此如果const在引入关键字后将文字更改为 require -qualification ,则会破坏遗留代码。但是,C 的字符串文字是不可变的,因此更改内容是未定义的行为,即使它没有const限定。

另一方面,C++ 是用const关键字设计的。最初,C++ 确实允许将字符串文字分配给非const限定的char *s,大概是为了与现有的 C 代码兼容。然而,从 C++03 标准开始,他们决定弃用此功能,而不是让这种不和谐持续下去。我猜想依赖于指向字符串文字的非const限定char *s的遗留 C++ 代码的数量足够小,这是一个值得权衡的。

  • 请注意,C++ 最初允许将非常量 `char*` 作为文字。但它已被弃用并在 C++11 中被正式删除。因此,即使 C++ 最初设计时考虑到了“const”,该规则的例外也被保留了一段时间。 (9认同)