2010-11-23 23 views
9

在C++中改變一個for循環內的循環變量被允許:如何顯示循環控制變量在C++ for-loop內部沒有改變?

for(int i = 0; i < limit; i++) { 
    if(condition) { 
     i--; 
    } 
} 

現在,如果一個循環體是相當複雜它不是立即顯而易見的讀者循環變量是否改變循環內身體。這會很好地調整代碼,以便一旦閱讀器只看到for循環頭部,他立即知道循環變量不會改變。

例如,如果我使用const

const int value = computeValue(); 
//lots of code here 

那麼很顯然,無論代碼如下const變量定義變量是不變的寫入。

有沒有辦法實現類似的東西 - 迭代內的邏輯常量 - 在C++中的for循環控制變量的情況下?

+3

我相信`std :: for_each`可以做到這一點。 – kennytm 2010-11-23 11:51:18

+0

我用`BOOST_FOREACH`獲得了巨大成功。你甚至可以在預編譯頭文件中引入一個方便的`#define foreach BOOST_FOREACH`。 – 2010-11-23 12:26:38

回答

1

沒有合理的結構來強制執行此操作。如果您將'const int idx = i'作爲循環中的第一條語句,然後僅使用'idx',則可能可以實現類似的強制執行,但會損失一些清晰度。否則,只需使用評論。

0

您可能會嘗試將您的「循環」變量名稱變成漫長而荒謬的事物,以至於在循環內觸摸它(不止一次)會刮傷眼睛。

還有些喜歡使用專用循環宏,如BOOST_FOREACH。這隱藏了循環變量/迭代器。

4

我不認爲這是可能的手工循環,但我想這可以被認爲是一個額外的參數,鼓勵使用std::for_eachBOOST_FOREACH迭代超過STL容器。

編輯 ...而C++ 0x中range-based for-loop(感謝馬修... M :)

+0

+1,比我做得更好,更乾淨! :) – 2010-11-23 12:22:38

2

這是一個很大的問題,讓我開始思考,你會如何做,以及如何解決它。無需花費太多時間,我想出的唯一的事情是:

int limit = 10; 
for(int i(0), guard(0); i < limit; i++, guard++) 
{ 
     // lots of code here 
    assert(i == guard); 
} 

顯然,用戶仍可以修改後衛循環,但也許在頂部的inention表明,它是要進行檢查。

1

技術上你可以做例如

int main() 
{ 
    for(int i = 0; i < 42; ++i) 
    {{ 
     typedef void i; 

     i = 666;  // !Nope. 
    }} 
} 

如果你想在typedef之前的循環體,那麼你就必須提供一個備用名稱(指const)內訪問i

但我不推薦這種技術解決方案,因爲它很模糊不常見,所以對讀者來說不是很明顯。

相反,只是重構大循環。:-)

1

您可以使for循環的整個主體成爲一個單獨的函數,爲此,循環控制變量超出了範圍。

我想不出一個簡單的方法來做你想做的事情,因爲循環控制變量是定義可變的,以控制循環。

2

C++ 0x好玩。此代碼不會被編譯:

 
for (int i = 0; i < 10; ++i) 
{ 
    [&, i]() 
    { 
     if (i == 5) 
     { 
      ++i; 
     } 
     cout << i << endl; 
    }(); 
} 

錯誤: 「I」:一個由值捕獲不能在非易變的拉姆達

2

使用的for_each與boost::counting_iterator組合和一個函數,它接受一個const被修改INT。

for_each(boost::counting_iterator<int>(0), boost::counting_iterator<int>(limit), 
    [&](const int i) 
    { 
     // do something with i 
    }); 
1

與需要FILELINE宏可能創建一個奇怪的物體,後者作爲模板參數(它是一個編譯時間常數τ)。隨着您增加它,它必須使用相同的FILELINE。那麼同一條線可能就足夠了。如果它不在同一行上,則可能會出現編譯器錯誤。

template< int line > 
class Counter 
{ 
// stuff 
public: 
    bool valid() const; 
    static void inc(Counter<line> & counter); 
}; 

for(Counter<__LINE__> counter(n); counter.valid(); Counter<__LINE__>::inc(counter)) 
{ 
// body 

    // what __LINE__ do I need to use here to increment counter? Can be done but won't be 
} 

我還沒有測試過它。只是一個想法。