[英]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.