c++ Initializing std::vector< int> with square brackets [] inside; what is happening?

qpgpyjmq  于 2022-12-30  发布在  其他
关注(0)|答案(1)|浏览(110)

激发我提出问题的背景信息:

我在C中学习了Designated Initializers,它非常棒,并且允许你像这样在C中初始化C数组,这非常棒:

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

我在C中试过了,但是它不起作用(请看我在上面的答案链接下的评论)。真糟糕。我在Cstd::vector中试过了,但是得到了我不理解的行为。这里发生了什么?

我问题的关键在于:

在我的例子中,[7] = 12[10] = 15在做什么?那里发生了什么?为什么编译?为什么输出是这样的?
我刚刚用-Wall -Wextra -Werror -Wpedantic编译了下面的代码,它仍然没有任何警告。-Wpedantic是我几乎从来没有使用过的,也不推荐使用,因为它关闭了编译器扩展,而我喜欢继续使用它。然而,我仍然没有收到任何警告与不寻常的[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

但是,如果没有-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中修复。请参见此答案下方的注解:
我想说,这是以前版本的编译器的一个普遍问题,因为GCC 8.4确实编译了它:https://godbolt.org/z/xqYq6jeb8。从9.1版本开始,错误开始出现。-Erdal Küçük

xzlaal3s

xzlaal3s1#

快速回答

为什么这个"工作"在这里?发生了什么?

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

详情

如需简短概述,请查看:https://www.modernescpp.com/index.php/designated-initializers.
Especially at the paragraph: 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
您可以在其中阅读以下内容:
这个扩展在GNU C++中没有实现。
既然您正在使用std::vector,那么请看一下如何构造vectorhttps://en.cppreference.com/w/cpp/container/vector/vector
第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一节中,您将能够阅读以下内容:
注意:乱序指定初始化、嵌套指定初始化、指定初始化式和正则初始化式的混合以及数组的指定初始化在C编程语言中都支持,但在C
中不允许。
经过一些讨论,我们发现,这些问题与编译器(版本)的不同实现有关。
由于标准和例如编译器GCC声明,指定的初始化式在C语言中支持,但在 C++ 中不支持,因此GCC版本8.4(OP的版本)编译时仍然没有任何警告和/或错误(参见:https://godbolt.org/z/xqYq6jeb8)。在版本9.1之后,错误将开始出现。

相关问题