兩者都可用於將函數應用於一系列元素。std :: transform和std :: for_each有什麼區別?
在高水平:
std::for_each
忽略函數的返回值, 保證執行順序。std::transform
分配返回值迭代器,並沒有 不能保證執行順序。
如果你喜歡使用一個與其他?有沒有什麼細微的警告?
兩者都可用於將函數應用於一系列元素。std :: transform和std :: for_each有什麼區別?
在高水平:
std::for_each
忽略函數的返回值, 保證執行順序。std::transform
分配返回值迭代器,並沒有 不能保證執行順序。如果你喜歡使用一個與其他?有沒有什麼細微的警告?
std::transform
相同map
。這個想法是對兩個迭代器之間的每個元素應用一個函數,並獲得由應用這種函數產生的元素組成的不同容器。您可能希望將其用於例如將對象的數據成員投影到新的容器中。在下文中,std::transform
用於將容器std::string
轉換成容器std::size_t
s。
std::vector<std::string> names = {"hi", "test", "foo"};
std::vector<std::size_t> name_sizes;
std::transform(names.begin(), names.end(), std::back_inserter(name_sizes), [](const std::string& name) { return name.size();});
另一方面,您執行std::for_each
唯一的副作用。換言之,std::for_each
與基於範圍的簡單的for
循環非常相似。
回到字符串例子:
for (std::size_t name_size: name_sizes) {
std::cout << name_size << std::endl;
}
對此進行擴展,在C++ 14中,我們可以從基於循環的範圍中刪除類型,現在成爲:for(name_size:name_sizes){...} –
不錯!上次我檢查它只是一個建議。我通常使用'for(auto && x:xs)',但是這種抽象級別對於解釋並不重要。 –
@TrevorHickey我很快再次檢查,除了最初的建議N3853之外,我找不到任何消息。你確定嗎? –
使用std ::變換分析是,當你想將字符串轉換爲大寫,你可以寫這樣的代碼的真實的例子:
std::transform(s.begin(), s.end(), std::back_inserter(out), ::toupper);
,如果你將盡力達成同樣的事情的std :: for_each的像:
std::for_each(s.begin(), s.end(), ::toupper);
它不會將其轉換爲大寫的字符串
你高:
std::for_each(name_sizes.begin(), name_sizes.end(), [](std::size_t name_size) {
std::cout << name_size << std::endl;
});
的確,從C++ 11相同的開始可以用更簡潔表示法使用基於範圍的for
環路來實現層次概述
std::for_each
忽略該函數的返回值並保證執行順序。std::transform
將返回值賦給迭代器,並不保證執行順序。
幾乎涵蓋了它。
看着它的另一種方法(優先於其他);
一件事記(微妙的警告)來承擔是在std::transform
的操作之前,和C++ 11(從en.cppreference.com)之後的要求的變化;
基本上這些是允許未確定的執行順序。
什麼時候使用一種?
如果我想操縱某個範圍內的每個元素,那麼我使用for_each
。如果我必須從每個元素計算出一些東西,那麼我會使用transform
。 當使用for_each
和transform
時,我通常將它們與lambda進行配對。
這麼說,我覺得我現在的傳統for_each
的使用,因爲基於範圍的出現正在有所縮水for
循環和lambda表達式在C++ 11(for (element : range)
)。我發現它的語法和實現非常自然(但是這裏的里程會有所不同),並且對於某些用例更直觀。
雖然問題已經得到解答,但我相信這個例子會進一步澄清這個區別。
for_each
屬於非修改STL操作,這意味着這些操作不會更改集合元素或集合本身。因此,for_each返回的值始終被忽略,並且未分配給集合元素。 儘管如此,仍然可以修改集合的元素,例如,當使用引用將元素傳遞給f函數時。應該避免這樣的行爲,因爲它不符合STL原則。
相反,transform
函數屬於修改STL操作並將給定的謂詞(unary_op或binary_op)應用於集合或集合的元素,並將結果存儲在另一個集合中。
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
void printer(int i) {
cout << i << ", ";
}
int main() {
int mynumbers[] = { 1, 2, 3, 4 };
vector<int> v(mynumbers, mynumbers + 4);
for_each(v.begin(), v.end(), negate<int>());//no effect as returned value of UnaryFunction negate() is ignored.
for_each(v.begin(), v.end(), printer); //guarantees order
cout << endl;
transform(v.begin(), v.end(), v.begin(), negate<int>());//negates elements correctly
for_each(v.begin(), v.end(), printer);
return 0;
}
它將打印:
1, 2, 3, 4,
-1, -2, -3, -4,
說不出效果是錯誤的。它有一個效果,即它否定整數。但是,它不存儲在內存中。 –
@JossieCalderon我編輯了我的答案,我希望它現在更清晰。 – BugShotGG
'transform'具有的輸出範圍,'for_each'沒有。 – user657267
很多''由非常相似的功能組成,只有*輕微*差異。 –
o11c
@ o11c這正是我要找的。這個細微差別肯定有很好的理由。 – bendervader