繁体   English   中英

在基于范围的临时std :: initializer_list上进行迭代

[英]Iterating over a temporary std::initializer_list with range based for

给定此代码

#include <iostream>
#include <initializer_list>
#include <string>

int a, b;

int main() {
    for (auto p : std::initializer_list<std::pair<int &, std::string>>{
        { a, "a" },
        { b, "b" },
    })
    {
        std::cout << p.second << ": " << p.first << '\n';
    }
}

我期望输出

a: 0
b: 0

gccclang同意,但是, Visual Studio 2013 Update 5(我的版本,不确定rextester使用的是什么)不同意并打印以下内容:

: 0
: 0

Visual Studio的std::initializer_list存在问题 ,但是应该认为它自更新2起已得到修复。

这是Visual Studio中的错误,还是我正在调用未定义或未指定的行为?

cppreference的“说明”部分中,range-for循环等效于:

{
    auto && __range = range_expression ;
    for (auto __begin = begin_expr,
                __end = end_expr;
            __begin != __end;
            ++__begin) {
        range_declaration = *__begin;
        loop_statement
    }
}

您可以看到迭代范围( range_epxression )已绑定到转发引用。 在您的情况下,后者将成为右​​值引用,因为您的initializer_list是临时的,因此其生存期延长到整个for循环。

MSVC在这里是错误的。

来自cppreference.com:

原始初始化程序列表对象的生存期结束后,不能保证基础数组存在。 未指定std :: initializer_list的存储(即取决于情况,它可以是自动,临时或静态只读存储器)。 (直到C ++ 14)

基础数组是一个临时数组,其中的每个元素都从原始初始化程序列表的相应元素进行了复制初始化(除非缩小转换无效)。 基础数组的生存期与任何其他临时对象相同,不同之处在于,从数组初始化initializer_list对象可以延长数组的生存期,就像将引用绑定到临时对象一样(但有相同的例外,例如用于初始化非临时对象)。 -static类成员)。 底层数组可以分配在只读存储器中。 (自C ++ 14起)

由此推断,编译器有错误,因为initializer_list的生存期应在大括号后结束。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM