从字符串字面值初始化字符数组是否属于数组复制初始化的情况?

Would initialising a character array from a string literal be a case of array copy initialisation?

本文关键字:初始化 数组 复制 情况 属于 是否 字符串 字符 字面值      更新时间:2023-10-16

在我的脑海中,我一直认为用文字的类型和值的临时变量代替文字的任何使用是好的。如果这个的情况下,因为字符串字面值的类型是const char数组将初始化一个字符数组通过字符串字面值不被认为是数组复制初始化?如不会

const char test1[] = "hello";

在某种程度上与做…相同

const char temp[6] = {'h', 'e', 'l', 'l', 'o', ''};
const char test2[] = temp;

将被禁止,因为这是一个数组复制初始化的例子?如果字面值的类型数组,那么如何使用字符串字面值来初始化数组?也许有些相关,如果字符串字面量是const char类型的数组,那么下面的代码如何在我的系统上编译得很好?

char* test3 = "hello";

由于test3缺少低级const,编译器错过了这种非法转换,但它编译得很好?当然,试图通过test3更改任何元素都会导致程序崩溃。

对于数组,复制和直接初始化没有区别。这两种情况都由编译器处理。你在开头所做的类比更多的是一个经验法则。实际上,一个数组不能被另一个数组初始化,除非它是字符串字面值。顺便说一句,你的类比并不完全正确。目标数组将使用临时数组直接初始化:

const char test2[](test1);

但是由于同样的原因,这仍然无法编译。这就是字符数组初始化的工作原理。

[dcl.init]/p17:

初始化式的语义如下:目标类型是被初始化的对象或引用的类型,源类型是初始化表达式的类型。如果初始化式不是单个(可能带圆括号)表达式,则未定义源类型。

  • 如果初始化器是(未加括号的)带括号的init-list,对象或引用被列表初始化(8.5.4)。
  • 如果目的类型是引用类型,请参见8.5.3。
  • 如果目标类型是字符数组、char16_t数组、char32_t数组或wchar_t数组,且初始化项是字符串字面值,请参见8.5.2

8.5.2:

窄字符类型(3.9.1)的数组、char16_t数组、char32_t数组、wchar_t数组可以通过窄字符串字面值、char16_t字符串字面值、char32_t字符串字面值或宽字符串字面值进行初始化。分别,或用大括号括起来的适当类型的字符串字面值(2.13.5)。字符串字面值的连续字符初始化数组的元素。(例子:

char msg[] = "Syntax error on line %sn";

显示了一个字符数组,其成员用字符串字面值初始化。[. .]

在您的另一个示例中,字符串字面值衰减为指向其第一个元素的指针,test3就是用这个元素初始化的。这段代码在c++ 111中无效,因为衰减的指针是const char*,但在C中这是一个有效的转换,因为字符串字面值是非const的。在c++ 03之前,它是被允许使用的,但后来被弃用了。


1:一些编译器仍然允许c++ 11中的转换作为扩展。