这些带有 char 数组的新表达式中哪些是格式良好的?

cig*_*ien 5 c++ new-operator language-lawyer c++20

对于以下程序

int main() 
{
    new char[4] {"text"};  // #1
    new char[5] {"text"};  // #2
    new char[] {"text"};   // #3
}
Run Code Online (Sandbox Code Playgroud)

clang 给出了一个错误,#1其中说:

error: initializer-string for char array is too long
Run Code Online (Sandbox Code Playgroud)

并接受#2#3

gcc 为所有语句给出以下错误:

error: invalid conversion from 'const char*' to 'char' [-fpermissive]
Run Code Online (Sandbox Code Playgroud)

此外,#3它给出了错误:

error: expected primary-expression before ']' token
Run Code Online (Sandbox Code Playgroud)

那么该语言对这段代码是否格式良好有什么看法呢?

我想知道当前的规则,但我也很想知道这是否在该语言的先前版本中发生了变化。

Nic*_*las 11

好的,这很容易追踪。的存在{}意味着正在执行列表初始化,因此我们可以访问规范中我们最喜欢的部分:[dcl.init.list]/3

在情况 1 中被初始化的对象是 a char[4]。花括号初始化器列表不是指定的初始化器,因此 3.1 被忽略。char[4]不是一个类,所以 3.2 被忽略。这将我们带到 3.3

否则,如果T是一个字符数组,并且初始化器列表有一个元素是适当类型的字符串文字 ([dcl.init.string]),则按照该子条款中的描述执行初始化。

嗯,char[4]肯定是字符数组,并且初始化列表肯定包含单个元素,并且该元素实际上与字符数组的类型匹配。所以我们去[dcl.init.string]

这告诉我们(在时尚之后):

string-literal 值的连续字符初始化数组的元素。

但下一段警告:

初始化器的数量不应多于数组元素。

好吧,这使得 #1 格式错误。

因此,我们重做char[5]. 这不会触发,因为 5 足够大。

最后,我们来到char[]. 就初始化而言,这与使用数字没有什么不同。char[]是一个字符数组,所以它遵循上述规则。C++17 会因为char[]new表达式中使用而窒息,但C++20 可以很好地使用它

如果 type-id 或 new-type-id 表示未知边界的数组类型([dcl.array]),则不应省略 new-initializer;分配的对象是一个包含 n 个元素的数组,其中 n 由 new-initializer ([dcl.init.aggr], [dcl.init.string]) 中提供的初始元素的数量确定。

这意味着#2 和#3 应该是合法的。所以 GCC 使它们格式错误是错误的。由于错误的原因,它使 #1 格式错误。