Primero, algunas reglas generales:
Úselo std::unique_ptrcomo un puntero inteligente sin gastos generales. No debería tener que molestarse con punteros crudos con tanta frecuencia. std::shared_ptrTambié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::arraypara matrices de longitud estática y std::vectorpara dinámico.
Use algoritmos genéricos ampliamente, en particular:
<algorithm>
<numeric>
<iterator>
<functional>
Uso autoy 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, accumulateY erase- remove_ifson buenos edad funcional map, foldy filter. Pero for_eaches 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);