以下是该问题的精简版本:
#include <initializer_list>
#include <iostream>
enum objects { zero, one, two, three, four, five, six, seven };
std::initializer_list<objects> objects_list()
{
return { zero, one, two, three, four, five, six, seven };
}
int main()
{
for (auto a : objects_list())
{
std::cout << a << ' ';
}
std::cout << '\n';
}
我的期望是节目输出:
0 1 2 3 4 5 6 7
这是由GCC 4.9.2确认的,但GCC新鲜的GCC存储库产生:
0 0 -85997960 32712 -1076836160 32765 0 32
似乎基本上是随机数字。
我的程序或GCC有问题吗?
答案 0 :(得分:5)
N4296§8.5.4/ 5州
类型为
std::initializer_list<E>
的对象是从初始化列表构造的,就像实现一样 分配了N
个const E
个元素的临时数组,其中N
是元素的数量 初始化列表。使用初始化程序的相应元素对该数组的每个元素进行复制初始化 列表,构造std::initializer_list<E>
对象以引用该数组
所以我们被告知std::initializer_list
指的是一个临时数组。
和§8.5.4/ 6陈述
该数组与任何其他临时对象具有相同的生命周期
该标准提供了此示例,以演示在数组超出范围后访问初始化列表是未定义的行为:
struct A {
std::initializer_list<int> i4;
A() : i4{ 1, 2, 3 } {} // creates an A with a dangling reference
};
initializer_list
对象在构造函数中初始化 ctor-initializer ,因此数组只会持续存在,直到构造函数退出,因此对i4
元素的任何使用都是如此 构造函数退出后产生未定义的行为。 - 例子]
您有一个类似但略有不同的例子涉及复制:
std::initializer_list<objects> objects_list()
{
return { zero, one, two, three, four, five, six, seven };
}
根据标准中的逻辑,数组{zero, one, two, ...}
仅在objects_list
函数的持续时间内持续存在。
18.9 / 2 [support.initlist]也支持副本不会持久保存基础数组:
复制[
std::
]initializer list
不会复制基础元素。
所以我相信你的代码最终是UB,之前它运作的事实是运气。