简体   繁体   English

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

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

Given this code 给定此代码

#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';
    }
}

I expect the output 我期望输出

a: 0
b: 0

and gcc and clang agree, however, Visual Studio 2013 Update 5 (my version, not sure what rextester uses) disagrees and prints this: gccclang同意,但是, Visual Studio 2013 Update 5(我的版本,不确定rextester使用的是什么)不同意并打印以下内容:

: 0
: 0

Visual Studio had an issue with std::initializer_list , but it is supposed have been fixed since update 2. Visual Studio的std::initializer_list存在问题 ,但是应该认为它自更新2起已得到修复。

Is this a bug in Visual Studio or am I invoking undefined or unspecified behavior? 这是Visual Studio中的错误,还是我正在调用未定义或未指定的行为?

From the "Explanation" section on cppreference , a range-for loop is equivalent to : cppreference的“说明”部分中,range-for循环等效于:

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

You can see that the iterated range ( range_epxression ) is bound to a forwarding reference. 您可以看到迭代范围( range_epxression )已绑定到转发引用。 In your case the latter turns into an rvalue reference, since your initializer_list is a temporary, and its lifetime is thus extended to the whole for loop. 在您的情况下,后者将成为右​​值引用,因为您的initializer_list是临时的,因此其生存期延长到整个for循环。

MSVC is wrong here. MSVC在这里是错误的。

from cppreference.com: 来自cppreference.com:

The underlying array is not guaranteed to exist after the lifetime of the original initializer list object has ended. 原始初始化程序列表对象的生存期结束后,不能保证基础数组存在。 The storage for std::initializer_list is unspecified (ie it could be automatic, temporary, or static read-only memory, depending on the situation). 未指定std :: initializer_list的存储(即取决于情况,它可以是自动,临时或静态只读存储器)。 (until C++14) (直到C ++ 14)

The underlying array is a temporary array, in which each element is copy-initialized (except that narrowing conversions are invalid) from the corresponding element of the original initializer list. 基础数组是一个临时数组,其中的每个元素都从原始初始化程序列表的相应元素进行了复制初始化(除非缩小转换无效)。 The lifetime of the underlying array is the same as any other temporary object, except that initializing an initializer_list object from the array extends the lifetime of the array exactly like binding a reference to a temporary (with the same exceptions, such as for initializing a non-static class member). 基础数组的生存期与任何其他临时对象相同,不同之处在于,从数组初始化initializer_list对象可以延长数组的生存期,就像将引用绑定到临时对象一样(但有相同的例外,例如用于初始化非临时对象)。 -static类成员)。 The underlying array may be allocated in read-only memory. 底层数组可以分配在只读存储器中。 (since C++14) (自C ++ 14起)

From this I would infer that the compiler is in error since the lifetime of the initializer_list should end after the closing brace. 由此推断,编译器有错误,因为initializer_list的生存期应在大括号后结束。

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

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