簡體   English   中英

在基於范圍的for循環中使用聲明的變量

[英]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);
}

在大多數情況下,不會使用不同位置的值,而是使用位置本身的元素:

  1. 當改變序列中的元素時,值實際上沒有幫助。
  2. 在大多數情況下,復制值很昂貴,並且保持參考更有效。
  3. 甚至有些情況下無法復制對象。

作為結果的設計者基於范圍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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM