Home c++ What is the difference between foreach and std :: for_each in C++?

What is the difference between foreach and std :: for_each in C++?

Author

Date

Category

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 make for_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

Programmers, Start Your Engines!

Why spend time searching for the correct question and then entering your answer when you can find it in a second? That's what CompuTicket is all about! Here you'll find thousands of questions and answers from hundreds of computer languages.

Recent questions