簡體   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