Primero, algunas reglas generales:
Úselo std::unique_ptr
como un puntero inteligente sin gastos generales. No debería tener que molestarse con punteros crudos con tanta frecuencia. std::shared_ptr
También es innecesario en la mayoría de los casos. Un deseo de propiedad compartida a menudo revela una falta de pensamiento sobre la propiedad en primer lugar.
Úselo std::array
para matrices de longitud estática y std::vector
para dinámico.
Use algoritmos genéricos ampliamente, en particular:
<algorithm>
<numeric>
<iterator>
<functional>
Uso auto
y decltype()
donde sea que beneficien la legibilidad. En particular, cuando se desea declarar una cosa, pero de un tipo que no se preocupan por como un iterador o tipo de plantilla compleja, el uso auto
. Cuando desee declarar una cosa en términos del tipo de otra cosa, use decltype()
.
Haga que las cosas sean seguras cuando sea posible. Cuando tienes afirmaciones que imponen invariantes en un tipo particular de cosas, esa lógica se puede centralizar en un tipo. Y esto no necesariamente implica una sobrecarga de tiempo de ejecución. También debería dejar de decir que los moldes de estilo C ( (T)x
) deben evitarse en favor de los moldes de estilo C ++ más explícitos (y buscables) (por ejemplo, static_cast
).
Finalmente, sepa cómo la regla de tres:
- Incinerador de basuras
- Copia constructor
- Operador de asignación
Se ha convertido en la regla de cinco con la adición del constructor de movimiento y el operador de asignación de movimiento. Y entienda las referencias de valor en general y cómo evitar la copia.
C ++ es un lenguaje complejo, por lo que es difícil de caracterizar mejor manera de utilizar todos de la misma. Pero las prácticas de un buen desarrollo de C ++ no han cambiado fundamentalmente con C ++ 11. Debería preferir los contenedores administrados por memoria en lugar de la administración manual de memoria: los punteros inteligentes facilitan hacer esto de manera eficiente.
Yo diría que el C ++ moderno está en su mayoría libre de administración manual de memoria. La ventaja del modelo de memoria de C ++ es que es determinista , no manual. Las desasignaciones predecibles hacen que el rendimiento sea más predecible.
En cuanto a un compilador, G ++ y Clang son competitivos en términos de características de C ++ 11 y se están poniendo al día rápidamente en sus deficiencias. No uso Visual Studio, así que no puedo hablar a favor ni en contra.
Finalmente, una nota sobre std::for_each
: evitarlo en general.
transform
, accumulate
Y erase
- remove_if
son buenos edad funcional map
, fold
y filter
. Pero for_each
es más general y, por lo tanto, menos significativo: no expresa ninguna otra intención que no sea bucle. Además de eso, se usa en las mismas situaciones que en el rango for
, y es sintácticamente más pesado, incluso cuando se usa sin puntos. Considerar:
for (const auto i : container)
std::cout << i << '\n';
std::for_each(container.begin(), container.end(), [](int i) {
std::cout << i << '\n';
});
for (const auto i : container)
frobnicate(i);
std::for_each(container.begin(), container.end(), frobnicate);