c++ - 用方括号 [] 初始化 std::vector<int> ;怎么了?

标签 c++ vector initialization g++ designated-initializer

有关激发我的问题的背景信息:

我了解了 C 中的 Designated Initializers,它很棒,并且允许您像这样在 C 中初始化 C 数组,这很棒:

int my_array[] = 
{
    [MY_ENUM1] = 7,
    [MY_ENUM5] = 6,
};

我在 C++ 中尝试过它,但它不起作用(上面链接的答案下的 see my comments)。无赖。我在 C++ std::vector 中尝试了它,但得到了我不理解的行为。这里发生了什么?

我的问题的关键:

[7] = 12[10] = 15 在我的例子中做了什么?那里发生了什么?为什么要编译?为什么输出是这样?

我刚刚用 -Wall -Wextra -Werror -Wpedantic 编译了下面的代码,它仍然编译时出现零警告。 -Wpedantic is one I almost never use, and do not recommend ,因为它关闭了编译器扩展,我喜欢继续这样做。然而,对于这种不寻常的 [7] = 12 语法,我仍然没有收到任何警告。

更新:onlinegdb 接受我的编译器标志的能力似乎有问题。使用 -Wpedantic 我在本地运行它时确实看到了警告:

eRCaGuy_hello_world/cpp$ g++ -Wall -Wextra -Werror -Wpedantic -O3 -std=c++17 vector_with_square_brackets.cpp -o bin/a && bin/a
vector_with_square_brackets.cpp:19:5: error: ISO C++ does not allow C99 designated initializers [-Werror=pedantic]
     [7] = 12, // Why does this "work" here? What is happening?
     ^
vector_with_square_brackets.cpp:20:5: error: ISO C++ does not allow C99 designated initializers [-Werror=pedantic]
     [10] = 15,
     ^
cc1plus: all warnings being treated as errors

WithOUT -Wpedantic,但是,我没有看到任何警告或错误:

eRCaGuy_hello_world/cpp$ g++ -Wall -Wextra -Werror -O3 -std=c++17 vector_with_square_brackets.cpp -o bin/a && bin/a
1
2
3
12
15
4

...但是输出仍然不遵循指定初始化器的规则。 我是否处于编译器错误之类的领域?我仍然希望获得更多答案和清晰度。

我的g++ --versiong++ (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0

请参阅我在下面代码中的注释:

在线运行:https://onlinegdb.com/FZ2YdZXJe(gcc编译器设置为C++17)

#include <iostream>
#include <vector>

std::vector<int> v =
{
    1,
    2,
    3,
    [7] = 12, // Why does this "work" here? What is happening?
    [10] = 15,
    4,
};

int main()
{
    for (int i : v)
    {
        std::cout << i << "\n";
    }
    printf("\n");

    return 0;
}

输出:

1
2
3
12
15
4

此外,我实际上希望输出看起来像这样,假设它在 C 数组中的作用类似于“指定的初始值设定项”。由于我没有得到这个输出,所以我不明白的其他事情必须继续(因此这个问题)。

1
2
3
0
0
0
0
12
0
0
15
4

更新:它似乎是一个 GCC 编译器错误

...它存在于版本 8.4(我正在使用的版本)中,但已被版本 9.1 修复。请参阅此答案下方的评论:

I would say, this was a general issue with previous versions of the compilers, because GCC 8.4 does compile it: https://godbolt.org/z/xqYq6jeb8. Since version 9.1, errors starts to occur. – Erdal Küçük

最佳答案

快速回答

Why does this "work" here? What is happening?

它不是,它是非标准的。 这是一个编译器错误。 GCC 8.4 版(OP 的版本)编译时没有任何警告和/或错误(参见:https://godbolt.org/z/xqYq6jeb8)。 9.1版本之后开始出现错误。

详情

有关简短概述,请查看:https://www.modernescpp.com/index.php/designated-initializers .

特别是在段落:https://www.modernescpp.com/index.php/designated-initializers#h2-1-differences-between-c-and-c


查看 GCC 页面:https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html

在那里你可以阅读以下内容:

This extension is not implemented in GNU C++.


由于您正在使用 std::vector , 看看如何 vector可以构建:https://en.cppreference.com/w/cpp/container/vector/vector

第 1 号中列出的构造函数。 10 vector(std::initializer_list<T> init)允许像这样初始化:

//Constructs the container with the contents of the initializer list init. 
std::vector<int> v = {1, 2, 4};

初始化列表的文档可以在这里找到:https://en.cppreference.com/w/cpp/utility/initializer_list


C++ 中的一般初始化:https://en.cppreference.com/w/cpp/language/initialization

您最感兴趣的初始化类型是:Aggregate initialization

Designated initializers 部分,您将能够阅读以下内容:

Note: out-of-order designated initialization, nested designated initialization, mixing of designated initializers and regular initializers, and designated initialization of arrays are all supported in the C programming language, but are not allowed in C++.


经过一些讨论,我们发现,问题必须与编译器(版本)的不同实现有关。

由于标准,例如编译器 GCC 指出,C 语言支持指定的初始值设定项,但 C++ 语言不支持指定的初始值设定项,GCC 8.4 版(OP 的版本)编译时没有任何警告和/或错误(参见:https://godbolt.org/z/xqYq6jeb8)。 9.1版本之后开始出现错误。

关于c++ - 用方括号 [] 初始化 std::vector<int> ;怎么了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70873232/

相关文章:

c++ - 从最高到最低对 int vector 进行排序

c++ - 将作为参数传入的对象数组转换为 vector

ios - 如何在 IBAction 按钮中初始化 Tile 源一次

c# - 将数组的值分配给一行中的分隔变量

c++ - 如果容器不分配,STL 的 priority_queue 会重新分配吗?

c++ - BFMatcher knnMatch

ruby - 如何在 Ruby 中向矩阵添加列和行?

c++ - 如何将父类转换为子类

c++ - 构建 PBRT v2 错误 - 错误 1 ​​错误 U1077 : 'if' : return code '0x1'

c++ - C++中的数组类成员初始化