是的,这段代码是有效的。
请记住(对于C++17),编译器将通过构造语义上替换基于范围的for循环
{
auto && __range = {"one", "two", "three", "four"};
for (auto __begin = begin(__range), __end = end(__range); __begin != __end; ++__begin)
{
auto& numberString = *__begin;
/* ... */
}
}
你看,initializer_list
的生命周期被延长到替换中最外层作用域内的__range
的生命周期。
但请注意,如果范围表达式本身包含一个临时对象,仍然很容易导致未定义的行为:
struct some {
auto get_list() { return {"one", "two", "three", "four"}; }
};
some foo() { return some{ }; }
for(auto& numberString : foo().get_list()) { /* ... */ }
foo()
创建的临时对象的生命周期才会得到延长,从而使其变为有效。另请参见https://en.cppreference.com/w/cpp/language/range-for。get_list
返回some
的成员引用时才会是未定义的。就目前而言,foo
返回一个临时的some
对象,该对象的生命周期持续到完整表达式的结束,这足以在其上调用get_list
。get_list
返回一个临时对象,然后按照通常的规则进行寿命延长。 - Miles Budnekget_list
的,而且没有任何initializer_list返回值的生命周期延长会改变这一点。(一旦我将返回类型更改为std::initializer_list<const char*>
,GCC和Clang都会警告返回临时对象的地址) - Sebastian Redl
std::initializer_list
对象实际上将拥有一个包含循环的生命周期,因此它是有效的。 - Some programmer dude