Uso estándar preferido: gama basada para o std:: para cada


En C++11, hay dos bucles sobre todos los elementos (rango basado en for y for_each). ¿Hay alguna razón para preferir uno sobre el otro o hay situaciones en las que uno encaja mejor?

for (auto& elem: container) {
  // do something with elem
}

std::for_each(container.begin(), container.end(),
              [](Elem& elem) {
                // do something with elem
              });

Mi idea sería que el primero es más simple y es similar a los bucles basados en rango en otros lenguajes, mientras que el segundo también funciona para secuencias que no son contenedores completos y el segundo es más similar a otros std-algoritmos.

Author: Drew Dormann, 2012-04-03

2 answers

  1. for basado en rangos es obviamente más fácil de leer y escribir. Está especializado para esta tarea.

    EDIT: Puede romper un rango-for sin abusar de una excepción. (Aunque std::find_if sustituido por std::for_each permite esto también.)

  2. std::for_each, irónicamente, es la alternativa que en realidad está basada en rango y le permite seleccionar valores begin y end particulares en lugar de todo el contenedor. (EDITAR: Esto puede ser hackeado usando una clase simple range que proporciona begin y end miembros, como los proporcionados por Boost.)

    También for_each puede ser más elegante cuando se usan funciones de orden superior: se puede usar como argumento para bind, y el tercer argumento ya es un funtor.

Principalmente es una cuestión de estilo. Sin embargo, la mayoría de los lectores probablemente prefieren ver for ( auto &a : b ), y la mayoría de las implementaciones ahora lo soportan.

 28
Author: Potatoswatter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-04 01:19:03

std::for_each devuelve el funtor que se ha utilizado internamente en el bucle, por lo que proporciona un mecanismo limpio para recopilar información sobre los elementos de la secuencia. El bucle for basado en rango es solo un bucle, por lo que cualquier estado que se use fuera del bucle debe declararse fuera de ese ámbito. En su ejemplo, si el propósito de los bucles es mutar cada elemento de la secuencia, entonces no hay mucha diferencia en absoluto. Pero si no está utilizando el valor devuelto de la for_each entonces probablemente estés mejor con el bucle simple. Por cierto, el bucle basado en rango también funciona en matrices de estilo C y std:: strings.

Este es un ejemplo de usar el valor de retorno de for_each, aunque no es muy imaginativo o útil. Es solo para ilustrar la idea.

#include <iostream>
#include <array>
#include <algorithm>

struct Foo {
  void operator()(int i) { if (i > 4) sum += i;}
  int sum{0};
};

int main() {

  std::array<int, 10> a{1,2,3,4,5,6,7,8,9,10};
  Foo foo = std::for_each(a.begin(), a.end(), Foo());
  std::cout << "Sum " << foo.sum << "\n";
}
 11
Author: juanchopanza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-03 14:05:40