#c++
Я новичок в C++ Читаю пример и наткрулся на такую конструкцию std::for_each и не понял, зачем она нужна когда есть стандартный for(val v : array)? Протестировал на время выполнения #include#include #include #include #include #include #include using namespace std; using namespace std::chrono; void testDeleteIt() { std::vector workers; for (int i = 0; i < 1000000; ++i) { workers.push_back(i); } int count = 0; high_resolution_clock::time_point t1 = high_resolution_clock::now(); for (int &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 (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(), [&count](int &i) -> void { count += i; }); count = 0; __android_log_print(ANDROID_LOG_ERROR, "HERE", "HERE ::: %s", std::to_string(count).c_str()); duration = duration_cast (high_resolution_clock::now() - t2).count(); __android_log_print(ANDROID_LOG_ERROR, "TIME2", "TIME 2 ::: %s", std::to_string(duration).c_str()); } И получилось, что стандартный цикл выполныется почти в 2 раза быстрее TIME 1::: 10102 TIME 2 ::: 18459 И плюс в std::for_each еще и заморочки с лямбдой Так в чем тогда его преимущество?
Ответы
Ответ 1
Читаю пример и наткнулся на такую конструкцию std::for_each и не понял, зачем она нужна когда есть стандартный for(val v : array)? Все просто - std::for_each появился как минимум на 10 лет раньше. Поэтому, да, теперь есть стандартный for. Но Вы не единственный, кто задается таким вопросом. Но есть несколько особенностей. std::for_each умеет несколько дополнительных возможностей. std::for_each умеет работать с произвольным диапазоном, заданный двумя итераторами. Стандартный for умеет только begin-end. std::for_each можно перегрузить для своего типа и сделать цикл "быстрее" - потому что функция будет знать внутренности вашего типа. А ещё в 17 стандарт подвезли execution_policy. А это значит, что легким движением можно сделать for_each "многопоточным" и контейнер будет обрабатываться значительно быстрее. В ответе вы тестируете суммирование. Тогда используйте std::accumulate. У меня есть подозрение, что в первом случае компилятор разобрался, что Вы именно суммируете и просто заменил на формулу "суммы ряда". Clang так точно умеет. В этом случае сравнивать производительность двух циклов немного некорректно.Ответ 2
Вообще то стандартные алгоритмы(и не только) существуют для того, чтобы каждый раз не написать в ручную код, который уже написан в лучшем виде. Если утверждать, что std::for_each не нужен, то с таким успехом можно утверждать, что ни один стандартный алгоритм не нужен. Ведь всегда можно написать самому и алгоритм и класс, заменяющий стандартный... Кроме того std::for_each возвращает свой аргумент функтор, в котором может хранится важная информация. Написать в ручную то же самое можно, но часто проще и надежнее(во избежании ошибок) использовать именно стандартный алгоритм. В указанном вами конкретном примере, думаю уместнее обходиться без него. p.s. кроме того For-цикл по коллекции появился позже, чем этот алгоритм. И еще... пример, где можно работать с конкретным диапазоном, без использования std::for_each int m[6] = {2, 4, 6, 8, 10, 11}; for (int& i : m) { static size_t k = 0; if (k && k <= 3) ++i; ++k; } По этому примеру очевидно, что если последовательность будет состоять из 10000 элементов, а нам нужно обрабатывать какой то маленький диапазон , то все равно нужно пройтись по всем и еще каждый раз проверять условие, что намного дороже чем в std::for_each передать именно этот диапазон, и таким образом рассмотреть только этот диапазон
Комментариев нет:
Отправить комментарий