C STL中 for each 演算法存在的意義是什麼?

時間 2021-05-10 10:22:08

1樓:白東傑

三年過去了,我偶然看到了這個老問題。很多人已經說過 range-for 了,我想再補充一點。

C++ 的 range for 在 C++20 出來之前是個殘廢,只能順序迭代,不能反向,也不能 skip。所以有特別的迭代要求的時候就只好手寫傳統三段 for,而 Bjarne Stroustrup 表示手寫這種 for 是 error-prone 的;我覺得這時候用 for_each 就正好:

// skip the first two elemsfor_each

(std

::next

(my_vec

.begin

(),2

),my_vec

.end

(),my_func

);歸根結底還是因為以前的 C++ 沒有 lazy 的 filter, map 等玩意。C++20 加上了,起名叫 range,現在也正式加入了這個大家庭(真香)

2樓:

現在是這樣:

for(

auto&&v

:vec

)以後是ranges::view,而且用ranges是趨勢,除非約定某種辦法可以並行化逃(

3樓:劉雲賓

對容器中的每乙個元素都呼叫函式的方法有以下:

第一種:

for (std::vector::iterator it = ve.begin(); it < ve.end(); ++it)

f(*it);

for (std::vector::const_iterator it = ve.cbegin(); it < ve.cend(); ++it)

f(*it);

for (std::vector::iterator it = ve.begin(); it != ve.end(); ++it)

f(*it);

for (std::vector::const_iterator it = ve.cbegin(); it != ve.cend(); ++it)

f(*it);

第二種:

for (int i = 0; i != ve.size(); ++i)

f(ve[i]);

for (int i = 0; i < ve.size(); ++i)

f(ve[i]);

for (std::size_t i = 0; i != ve.size(); ++i)

f(ve[i]);

for (std::size_t i = 0; i < ve.size(); ++i)

f(ve[i]);

for (std::vector::size_type i = 0; i != ve.size(); ++i)

f(ve[i]);

for (std::vector::size_type i = 0; i < ve.size(); ++i)

f(ve[i]);

第三種:

std::for_each(ve.begin(), ve.end(), f);

std::for_each(ve.cbegin(), ve.cend(), f);

std::for_each(std::begin(ve), std::end(ve), f);

std::for_each(std::cbegin(ve), std::cend(ve), f); // C++14

第四種:

for (auto val : ve)

f(val);

for (auto &val : ve)

f(val);

for (const auto &val : ve)

f(val);

分析:第一種方法:

書寫太複雜

並不是所有容器的迭代器都支援小於操作

容易誤寫成 it <= ve.end()

第二種方法:

呼叫 ve.size()可能有效率的問題

呼叫 ve[i]可能有效率的問題

並不是所有的容器都支援下標操作

下標的標準規範是無符號的數,所以使用int 是錯誤的

標準並未說明下標具體用何種型別說明,所以使用std::size_t可能有可移植性的問題

使用 std::vector::size_type正確,但書寫太複雜了

容易誤寫為 i <= ve.size()

第三種方法:

相比前兩種,不容易出錯

相比前兩種,書寫也簡單多了

如果在函式呼叫處寫函式的話還是比較複雜

第四種方法:

相比前三種,不容易出錯

相比前三種,書寫更簡單了

直接在函式呼叫處寫函式也很簡單

需要 C++11 或之後

4樓:Eric Qiang

@塗祺招 說到了點子上:

stl::for_each最大特點就是純函式式程式設計,就是老老實實從begin給我迭代到end,沒有中途退出迴圈break,沒有直接跳下一步迴圈continue。這個語義清楚不清楚?

編譯器是不是可以盡情優化?

相反,你用傳統的for迴圈,或者C++11的range-based for,都無法讓編譯器相信你不會搞出半途來個break/continue這樣的夭蛾子。

對了,函式式程式設計就絕對不會整那些夭蛾子。所以它可以隨便併發重入(reentrant)

5樓:塗祺招

for_each 更明確了整個迴圈語義,有利於編譯器優化(比如 begin end 都是用的 const_begin const_end,可以認為迴圈一定不會修改容器,如果有多核,可以多核優化,同時跑)(滿足對映規約)

for 做不到,for只說了我要個迴圈,什麼時候中途break了改了上下文環境了,毫無保障。

也就是說編譯器可以從for_each裡獲得更多的語義。而for 把這些語義全搞丟了!

6樓:「已登出」

因為你寫的不好當你全都在用標準庫演算法的時候統一帶來的快感肯定會讓你強迫症發作的

::std::for_each(::std::begin(v),::std::end(v),::func);

for (auto &&e : v)

func(e);

7樓:tearshark

std::string沒有make lower函式。每次make lower,我都是foreach+tolower完成的。

8樓:邱昊宇

同樣是迴圈,同樣的效果,但不同的寫法抽象程度不同,語義不同。

你要的例子:

for (auto& e : employees)局長:小李啊,過年了,給我們每個員工發一箱蘋果。

小李:好的。

std::

for_each

(std

::begin

(employees

),std

::end

(employees

),);

局長:小李啊,過年了,給我們所有員工每人發一箱蘋果。

小李:好的。(咦?這強烈的既視感……)

for(

auto

iter

=std

::begin

(employees

);iter

!=std

::end

(employees

);++

iter

)局長:小李啊,過年了,你幫我把我們公司員工按順序叫來我辦公室。

小李:好嘞!

員工甲:局長,您叫我?

局長:啊,小甲,發你一箱蘋果。

員工乙:局長,您叫我?

局長:啊,小乙,發你一箱蘋果。

局長:啊,好好好,收工,哈哈哈。

小李:局長啊,這種事情,以後您說給每個員工發箱蘋果就好了,不用麻煩您老,我可以幫您辦。

for(

size_ti=

0;i<

employees

.size

();i++)

局長:小李啊,過年了,我問你,我們公司現在一共多少員工?

小李:兩千名員工。

局長:那你先把第乙個員工叫來。

小李:啊,好的。

員工一號:局長,您叫我?

局長:啊,小一,發你一箱蘋果。

局長:小李,剛才那個是幾號來著?

小李:一號。

局長:那好,你再幫我把二號叫來。

小李:啊,好的。

局長:小李,剛才那個是幾號來著?

小李:兩千號。

局長:那就是所有人都來過了是吧?

小李:是的……(MDZZ)

9樓:Alinshans

這一搜一大把呀!

Advantages of std::for_each over for loop

for loop vs std::for_each with lambda

for_each 好像看不出太大的優勢,為了防止你問出 accumulate 有什麼用,先放出這個

10樓:BlueWanderer

至少對於你這個個例,你可以寫for_each(data.begin(), data.end(), func)。

for_each畢竟還是可以少敲好多字的。當然別人會說這樣更可讀(很大程度還是因為少敲的那些東西)_(:з)∠)_

C STL中binary search的返回值為什麼是bool型別,而不是像c中bsearch那樣返回找到的元素的下標?

MouseHaoHao template ForwardIterator class T bool binary search ForwardIterator first ForwardIterator last constT val 沒辦法返回下標 而且如果有重複的話,下標是要返回 start p...

Java中foreach為什麼不能給陣列賦值?

顏欽能 給你舉乙個例子,你看一下可能比較能理解 for int element array1 question 為什麼用Foreach無法給陣列賦值element r.nextInt 101 1 System.out.println element 雖然可以輸出十個隨機數,但並沒有把十個隨機數賦給a...

請問,如何規避在foreach中運算元據庫,或者批量查詢?

其實各主流php框架都有這些細節的處理,國內yii用的多的話看文件唄 http www.拉到下面with語法,具體sql細節就是一次拿節約tcp來回消耗唄。 Lance Zhang 賈俊俊 答案裡面for裡面new物件的那個例子是錯的 最佳的方式應該是 new 物件a for x y 這樣寫,for...