C++ 在基于范围的临时std::initializer_列表上迭代
鉴于此代码C++ 在基于范围的临时std::initializer_列表上迭代,c++,visual-studio,c++11,undefined-behavior,compiler-bug,C++,Visual Studio,C++11,Undefined Behavior,Compiler Bug,鉴于此代码 #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" }, })
#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';
}
}
但是,2013年更新5(我的版本,不确定rextester使用什么)不同意并打印以下内容:
: 0
: 0
VisualStudio有一个带有std::initializer\u列表的列表,但它应该在更新2后得到修复
这是Visual Studio中的错误还是我调用了未定义或未指定的行为?从上的“解释”部分中,循环的范围相当于:
{
auto && __range = range_expression ;
for (auto __begin = begin_expr,
__end = end_expr;
__begin != __end;
++__begin) {
range_declaration = *__begin;
loop_statement
}
}
您可以看到迭代范围(range\u epxpression
)绑定到转发引用。在您的例子中,后者变成了右值引用,因为您的初始值设定项列表
是临时的,因此它的生存期将扩展到整个for
循环
MSVC在这里是错误的。来自cppreference.com:
在原始初始值设定项列表对象的生存期结束后,不能保证基础数组存在。std::initializer_列表的存储未指定(即,它可以是自动、临时或静态只读内存,具体取决于具体情况)。(直到C++14)
底层数组是一个临时数组,其中每个元素都是从原始初始值设定项列表的相应元素复制初始化的(缩小转换无效除外)。基础数组的生存期与任何其他临时对象的生存期相同,只是从数组初始化初始值设定项\u list对象会延长数组的生存期,就像将引用绑定到临时对象一样(除了相同的例外,例如初始化非静态类成员)。可以在只读内存中分配基础阵列。(从C++14开始)
从这一点,我可以推断编译器是错误的,因为初始值设定项列表的生命周期应该在右大括号结束后结束。我认为这是一个错误,我在connect上报告了它,从那时起它就被修复了,但我不记得是在更新中还是在2015年@NathanOliver无法复制,为我使用2015。@melak47我不确定我做了什么,但我重新测试了它,它现在在我的机器上工作。我删除了我的误导性评论。谢谢:)不是auto&&
实际上称为转发引用,还是仅当它是模板时才被称为转发引用?@NathanOliverauto
的行为类似于模板参数推断,因此它确实是一个转发引用,谢谢:)
{
auto && __range = range_expression ;
for (auto __begin = begin_expr,
__end = end_expr;
__begin != __end;
++__begin) {
range_declaration = *__begin;
loop_statement
}
}