MSVC 接受使用字符串文本初始化的 std::string 数组,但 gcc 和 clang 拒绝

MSVC accepts std::string array initialized with string literal but gcc and clang rejects

提问人:Alan 提问时间:11/8/2023 最后编辑:Alan 更新时间:11/8/2023 访问量:117

问:

我注意到带有 C++20 的 msvc 允许通过字符串文字初始化数组,但 gcc 和 clang 都拒绝它。演示std::string

#include <string>
int main()
{ 
       std::string a[] = "a";   //msvc c++20 accepts while msvc c++17 rejects and gcc and clang all versions rejects this 
}  

根据 C++ 标准,这里的正确行为应该是什么。

C++ 初始化 语言 - 律师 C++20 字符串文字

评论

1赞 user12002570 11/8/2023
@jpa 不,这是标准的缺陷。请参见CWG28244
0赞 Ted Lyngmo 11/8/2023
我很好奇,初始化之后是什么?std::size(a)a[0].size()
0赞 user12002570 11/8/2023
@TedLyngmo奇怪的是,当我用 C++20 添加 msvc 时,也开始出现其他错误。演示std::string b[] = {"a"}; std::cout << a << 1;
1赞 Ted Lyngmo 11/8/2023
@user12002570是的,我也明白了。我现在在家,可以尝试一下。:“没有匹配的过载”。然后我做了,得到了“错误C2070'std::string []':非法大小操作数”。 给出“错误 C4789 大小为 2 字节的缓冲区 'a' 将被溢出;将从偏移量 16 开始写入 8 个字节“,并且”错误 C4789 大小为 2 字节的缓冲区“a”将被溢出;16 个字节将从偏移量 0 开始写入“ - 完全令人困惑。std::size(a)(sizeof(a) / sizeof *(a))a[0].size()

答:

3赞 user12002570 11/8/2023 #1

这是指出程序应该格式不正确CWG2824,但当前的措辞(通过P0960R3引入)使其格式良好。

目前 dcl.init.general#16.5 中的措辞说:

否则,如果目标类型为数组,则按如下方式初始化对象。设 x1, . . . , xk 是表达式列表的元素。如果目标类型是未知边界的数组,则将其定义为具有 k 个元素。让 n 表示此潜在调整后的数组大小。如果 k 大于 n,则程序格式不正确。否则,第 i 个数组元素将复制初始化,每 1 个≤ i ≤ k 个 习,每个 k < i ≤ n 的值初始化。对于每 1 个 ≤ i < j ≤ n,与数组第 i 个元素的初始化相关的每个值计算和副作用都先于与第 j 个元素的初始化相关的值计算和副作用排序。


而正确/修订的措辞(如CWG2824中建议的)是:

否则,如果目标类型为数组,则按如下方式初始化对象。初始值设定项的格式应为 ( expression-list )。设 x1, . . . , xk 是表达式列表的元素。如果目标类型是未知边界的数组,则将其定义为具有 k 个元素。让 n 表示此潜在调整后的数组大小。如果 k 大于 n,则程序格式不正确。否则,第 i 个数组元素将复制初始化,每 1 个≤ i ≤ k 个 习,每个 k < i ≤ n 的值初始化。对于每 1 个 ≤ i < j ≤ n,与数组第 i 个元素的初始化相关的每个值计算和副作用都先于与第 j 个元素的初始化相关的值计算和副作用排序。

请注意上面句子中强调的部分,它使代码格式不正确


请注意,P0960 仅在 C++20 中引入了 dcl.init.general 中的措辞更改。也就是说,缺陷报告适用于 C++20 及更高版本。对于 C++17,不需要对措辞进行任何更改,因为 dcl.init#17.5 已经使程序格式不正确。