以下是问题的精简版:
#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';
}
Run Code Online (Sandbox Code Playgroud)
我的期望是方案产出:
0 1 2 3 4 5 6 7
Run Code Online (Sandbox Code Playgroud)
这是由GCC 4.9.2确认的,但GCC新鲜的GCC存储库产生:
0 0 -85997960 32712 -1076836160 32765 0 32
Run Code Online (Sandbox Code Playgroud)
这看起来基本上是随机数.
我的程序或GCC有问题吗?
N4296§8.5.4/ 5州
类型的对象
std::initializer_list<E>是从初始化列表构造的,就好像实现分配了一个临时N的类型元素数组const E,其中N是初始化列表中元素的数量.使用初始化列表的相应元素对该数组的每个元素进行复制初始化,并std::initializer_list<E>构造该对象以引用该数组
所以我们被告知a 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
};
Run Code Online (Sandbox Code Playgroud)
该
initializer_list对象在构造函数的 ctor-initializer中初始化,因此该数组仅在构造函数退出之前一直存在,因此i4在构造函数退出之后对元素的任何使用都会产生未定义的行为. - 末端的例子]
您有一个类似但略有不同的示例涉及复制:
std::initializer_list<objects> objects_list()
{
return { zero, one, two, three, four, five, six, seven };
}
Run Code Online (Sandbox Code Playgroud)
根据标准的逻辑,数组{zero, one, two, ...}仅在objects_list函数持续时间内持续存在.
18.9/2 [support.initlist]还支持副本不会持久保存基础数组:
复制[
std::]initializer list不会复制基础元素.
所以我相信你的代码最终是UB,之前它运作的事实是运气.
| 归档时间: |
|
| 查看次数: |
267 次 |
| 最近记录: |