为什么我可以在不使用赋值运算符的情况下使用列表初始化普通数组

Why can i initialize a plain array using a list without using assignment operator

本文关键字:列表 初始化 数组 情况下 赋值运算符 我可以 为什么      更新时间:2023-10-16

我在某人的代码中发现,我们可以使用列表在C++中初始化一个普通的 c 样式数组,而无需实际使用赋值运算符。代码是这样的:

int a[4]{1, 2, 3, 4};
for (int i =0; i < 4; i++){
    cout << a[i] << 'n';
}

上面的代码运行正常。上面的初始化就像我们如何在 C++ 中初始化 int 向量一样。我尝试在 C 中使用它。但这是不允许的。

为什么我们可以在C++中做到这一点,而在 C 中却不能这样做?从什么时候开始我们可以将这种初始化语法用于纯C++数组?你能给出这个语法的任何参考吗?我不知道在哪里可以找到它。

为什么我们可以在C++中做到这一点,而在 C 中却不能这样做?

C++和C是不同的语言。在 C 语言中,=是必需的。在C++(自 C++11 起(,它是可选的。

在C++中,它称为聚合初始化,其语法如下:

T object = {arg1, arg2, ...};
T object {arg1, arg2, ...};     // (since C++11)

有关更多详细信息:请参阅 C++ 规范中的第 8.5.1 节聚合 [dcl.init.aggr]。

在 C 中,初始化固定了一种形式

init-declarator:
    declarator
    declarator = initializer 
              ^^^

在C++中,有各种形式的初始化具有不同的语义。

C++初始化细分为具有复制初始化语义和直接初始化语义的初始化。

例如,非聚合类型的这些初始化A

A a = { 10 }; // copy-initialization

A a { 10 }; // direct-initialization

可以根据相应的构造函数是显式的还是非显式的,产生不同的结果。

考虑以下程序

int main()
{
    struct A
    {
        explicit A(int x) : x(x) {}
        int x;
    };
    A a1 { 1 };
    // A a2 = { 1 }; - compilation error
}

此外,在C++中还有初始值设定项列表和初始值设定项列表构造函数。

按以下方式修改前面的演示程序

#include <iostream>
#include <initializer_list>
#include <numeric>
int main()
{
    struct A
    {
        explicit A(int x) : x(x) 
        {
            std::wcout << "A::A( int )" << std::endl;
        }
        explicit A(std::initializer_list<int> lst) :
            x(std::accumulate(lst.begin(), lst.end(), 0)) 
        {
            std::wcout << "A::A( std::ininitializer_list<int> )" << std::endl;
        }
        int x;
    };
    A a { 1 };
}

并查看其输出。

在C中没有这样的细分。这没有意义,因为在它背后没有 C 中初始化的特殊语义。

在没有特殊语义的情况下引入不同形式的初始化只会让用户感到困惑。