[英]Using declared variable in a range-based for-loop
在下面的例子中, i
有功能范围。 但似乎我不能在第二个for循环中使用i
。 为什么for (i : v1)
不起作用,但for (int i : v1)
有效?
#include<iostream>
#include<string>
#include<vector>
int main()
{
std::vector<int> v1;
int i;
while(std::cin>>i)
{
v1.push_back(i);
}
for(i : v1) //for (int i:v1) works
std::cout<<i<<"\t";
cout<<std::endl;
return 0;
}
这是一个语法问题,基于范围的for
循环需要声明一个命名变量 ,即它需要一个类型说明符(cf,例如, cppreference.com ):
for(range_declaration:range_expression)loop_statement
range_declaration - 命名变量的声明 ,其类型是range_expression表示的序列元素的类型,或对该类型的引用。 经常使用auto说明符进行自动类型推导
其实我不知道为什么你的问题被贬低了; 我觉得你的假设很好; 只是C ++语法决定以另一种方式定义它。
基于范围的for
具体是指取代类似于下面的循环(这是一个有些简单化情况;基于范围for
,特别是C ++ 17版本,是更普遍的比例):
for (auto it = range.begin(), end = range.end(); it != end; ++it) {
use(*it);
}
在大多数情况下,不会使用不同位置的值,而是使用位置本身的元素:
作为结果的设计者基于范围for
决定,绝对引用必须支持。 与此同时,它的目的是使用一个比较简单的重写规则的范围为基础for
。 在标准中编纂的规则是:
for (<range-decl>: <range>) { <body> }
相当于
{
auto&& range = <range>; // keep the range alive!
auto it = begin(range); // actually, reality is bit more complicated
auto end = end(range); // actually, reality is a bit more complicated
for (; it != end; ++it) {
<range-decl> = *it; // this is the rewrite causing your issue
<body>
}
}
特别是,暗示<range-decl>
是一个声明,而不仅仅是命名变量。 这样做的原因的要求是,通常在前面使用的实体:
是一个参考。 但是,引用不能反弹。 但是,在循环的每次迭代中,可以使用新的引用。
原则上,如果<range-decl>
不是声明而是左值,则重写规则可以使用赋值。 那会产生一些奇怪的行为:
for (T const& x: range)
和T const& x = 0; for (x: range)
之间会有区别T const& x = 0; for (x: range)
T const& x = 0; for (x: range)
:前者有效,后者有误。 T& x = get_reference(); for (x: range) {...}
),则循环会自动将范围中的所有值分配给位于某处的对象。 通常,对象要么位于堆栈上,要么位于源范围内(当变量被声明为引用时)。 根据变量的声明方式,仅允许初始化比支持初始化或赋值更合理。 查看提案的修订历史( N2930和前任)并未引起讨论,但我含糊地回忆起这一点已经讨论过了。
当您使用基于范围的循环时,在打开括号后需要声明,而不仅仅是变量。 正确的语法是:
for ( declaration : range ) statement;
您可以看到此链接以获取更多信息。
在您的示例中 :当您在while
循环之前声明i
,您可以在所有main
函数中使用它,并且它的范围是main
函数。 您可以使用它在for
身体。 当你在for
范围中使用i
变量时,你没有声明它,因为你已经在上面声明了它,所以它会给你一个错误,并且它对C ++语法不正确。
但是当您在for
括号中的i
之前键入int
,您将声明另一个名为i
变量,但仅针对您的for
循环,然后使用C ++语法就可以了。
理由很可能是因为这将调用变量上的复制赋值 ,这将成为效率极低的潜在根源,并且在实践中几乎从不是意图......如果类型完全支持复制赋值。
所以他们可能认为最好禁止这个。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.