激发我提出问题的背景信息:
我在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
时,我确实在 * 本地 * 运行它时看到警告:**
- 更新:onlinegdb接受编译器标志的能力似乎有问题。使用
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++ --version
是g++ (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
1条答案
按热度按时间xzlaal3s1#
快速回答
为什么这个"工作"在这里?发生了什么?
详情
如需简短概述,请查看: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
,那么请看一下如何构造vector
:https://en.cppreference.com/w/cpp/container/vector/vector第10个
vector(std::initializer_list<T> init)
中列出的构造函数允许如下初始化:初始化器列表的文档可以在这里找到: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之后,错误将开始出现。