在以前,若是我們要針對 STL container 中的所有物件做事情,最「方便」的方法是使用 iterator 搭配傳統的 for-loop:

class Entry;
list<Entry> my_list;

void check_entries(void)
{
    for ( list::iterator<Entry> itor = my_list.begin(); itor != my_list.end(); ++itor)
    {
        Entry& e = *itor; // iterator 本身的操作類似 pointer
        // do something...
    }
}

那行 for 的敘述式真是又臭又長。即使是 C++11 導入了 auto 關鍵字,可以用來取代 itor 前面的型別,整體的可讀性還是很差。

幸好,C++11 同時導入了其他高階語言常見的 ranged for-loop,可以增加可讀性,也不用再 key 那麼多囉嗦的程式碼了:

void check_entries(void)
{
    for ( auto& e : my_list)
    {
        // do something...
    }
}

使用上有幾個需要注意的地方:

  1. 元素 e 的作用範圍 (scope) 僅在 for-loop 中。出了 for-loop 就不能用了(這是優點)。
  2. 若是型別的後面沒有 reference 符號 &,那麼 e 就是「複製出來」的物件,類似 C/C++ 中 call by value 的概念。此時 e 是不能修改的(或者說:就算修改了,也不會影響到 my_list 中對應物件的內容)。若是需要修改,就要加上 &
  3. 加上 & 還有一個優點,那就是不需要複製整個物件。這對於占用空間較大的物件(通常是使用者定義的 class 生出來的物件)來說比較有效率。
  4. 若是需要效率,又希望保有「唯讀」的特性,可以在型別前面加上 const。以此例來說,就是變成:for (const auto& e : my_list)

By closer

發表迴響