tex*_*uce 14 c++ language-lawyer c++11
我的代码如下:
#include <vector>
#include <iostream>
int main(){
for(int& v : std::vector<int>{1,3,5,10}) {
std::cout << v << std::endl;
v++; // Does this cause undefined behavior?
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
据我所知,向量是prvalue,并且无法绑定int&
,但是这个可以正常工作吗?
是因为范围循环只是宏扩展而且会为向量创建临时变量吗?
tem*_*def 17
根据C++ ISO规范,基于范围的for循环被正式定义为等价于
{
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr;
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,"等效于"并不意味着"扩展为宏",而是"具有与"完全相同的行为".这种等价不是传统意义上的宏(即它不是a #define
),而是在ISO规范中给出,作为定义基于范围的for循环的语义的形式方式.基于范围的for循环的实现可以是编译器喜欢的任何内容,只要该行为与上面给出的行为完全相同即可.
在这个上下文中,range_expression
是一个prvalue,但它然后被绑定__range
,这是一个左值.扫描得到的迭代器__range
也是左值,因此当取消引用迭代器以产生范围内的各个值时,这些值将是左值.
希望这可以帮助!
基于范围的for
循环绝对不是宏扩展.它是该语言的独立构造.尽管矢量本身是一个prvalue,但它的成员函数仍然正常运行.所以它operator[]
(或解除引用它的迭代器)返回一个正常的左值引用等.
当然,只要载体本身存在,这样的引用才有效.它的寿命持续整个基于范围的for
循环(这是for
标准中基于范围的循环规范所要求的),所以一切都很好.
就价值类别而言,它与此相同(这也是合法的):
int &i = std::vector<int>{1, 2, 3}[0];
Run Code Online (Sandbox Code Playgroud)
当然,与基于范围的for
循环中的那个不同,该i
引用立即变得悬空.但原则是一样的.
还要考虑这一点:语言无法知道迭代器operator *
或向量返回的左值引用operator[]
是指其生命周期与向量的生命周期绑定的东西.它只返回一个左值引用,因此它是可绑定的.
归档时间: |
|
查看次数: |
571 次 |
最近记录: |