I’m new to C++
I am reading an example and came across such a construction std :: for_each
and did not understand why it is needed when there is a standard for (val v: array)?
Tested for runtime
# include & lt; array & gt;
#include & lt; iostream & gt;
#include & lt; chrono & gt;
#include & lt; android / log.h & gt;
#include & lt; thread & gt;
#include & lt; fstream & gt;
#include & lt; utility & gt;
using namespace std;
using namespace std :: chrono;
void testDeleteIt () {
std :: vector & lt; int & gt; workers;
for (int i = 0; i & lt; 1000000; ++ i) {
workers.push_back (i);
}
int count = 0;
high_resolution_clock :: time_point t1 = high_resolution_clock :: now ();
for (int & amp; i: workers) {
count + = i;
}
__android_log_print (ANDROID_LOG_ERROR, "HERE", "HERE :::% s", std :: to_string (count) .c_str ());
count = 0;
long long int duration = duration_cast & lt; microseconds & gt; (high_resolution_clock :: now () - t1) .count ();
__android_log_print (ANDROID_LOG_ERROR, "TIME1", "TIME 1 :::% s", std :: to_string (duration) .c_str ());
high_resolution_clock :: time_point t2 = high_resolution_clock :: now ();
std :: for_each (workers.begin (), workers.end (), [& amp; count] (int & amp; i) - & gt; void {
count + = i;
});
count = 0;
__android_log_print (ANDROID_LOG_ERROR, "HERE", "HERE :::% s", std :: to_string (count) .c_str ());
duration = duration_cast & lt; microseconds & gt; (high_resolution_clock :: now () - t2) .count ();
__android_log_print (ANDROID_LOG_ERROR, "TIME2", "TIME 2 :::% s", std :: to_string (duration) .c_str ());
}
And it turned out that the standard loop runs almost 2 times faster
TIME 1 ::: 10102
TIME 2 ::: 18459
And plus in std :: for_each
there are also lambda troubles
So what is its advantage then?
Answer 1, authority 100%
I am reading an example and came across such a construction std :: for_each and did not understand why it is needed when there is a standard for (val v: array)?
It’s simple – std :: for_each
appeared at least 10 years earlier. Therefore, yes, there is now a standard for. But you are not the only one who asks this question .
But there are several peculiarities. std :: for_each
has several additional features.
std :: for_each
can work with an arbitrary range specified by two iterators. The standard for can only do begin-end.std :: for_each
can be overloaded for your type and make the loop “faster” – because the function will know the insides of your type.- And at 17 the standard brought up
execution_policy
. This means that with a slight movement you can makefor_each
“multithreaded” and the container will be processed much faster.
In your answer, you are testing summation. Then use std :: accumulate
. I have a suspicion that in the first case, the compiler figured out what you are summing up and simply replaced it with the “sum of the series” formula. Clang does just that. In this case, comparing the performance of the two loops is a bit incorrect.
Answer 2, authority 35%
In general, standard algorithms (and not only) exist in order not to write code by hand, which is already written in the best possible way.
If you argue that std :: for_each
is not needed, then you might as well argue that no standard algorithm is needed. After all, you can always write yourself an algorithm and a class that replaces the standard one … In addition, std :: for_each
returns its argument a functor in which important information can be stored. It is possible to write the same by hand, but it is often easier and more reliable (in order to avoid errors) to use the standard algorithm. In the specific example you specified, I think it would be more appropriate to do without it.
p.s. in addition, the collection For-loop appeared later than this algorithm. And one more … an example where you can work with a specific range, without using std :: for_each
int m [6] = {2, 4, 6, 8, 10, 11};
for (int & amp; i: m) {
static size_t k = 0;
if (k & amp; & amp; k & lt; = 3)
++ i;
++ k;
}
For this example, it is obvious that if the sequence will consist of 10000
elements, and we need to process some small range, then we still need to go through all of them and check the condition every time, which is much more expensive than in std :: for_each
to pass this exact range, and thus consider only this range