tipos programas librerias lenguaje ejemplos datos completo comandos avanzados c++ c++11 c++-faq

programas - qué modismos de C++ están en desuso en C++ 11



programas en c++ ejemplos avanzados pdf (9)

Con el nuevo estándar, hay nuevas formas de hacer las cosas, y muchas son más agradables que las antiguas, pero la forma antigua todavía está bien. También está claro que el nuevo estándar no se deprecia oficialmente, por razones de compatibilidad con versiones anteriores. Entonces la pregunta que queda es:

¿Qué formas antiguas de codificación son definitivamente inferiores a los estilos C ++ 11, y qué podemos hacer ahora?

Al contestar esto, puede omitir las cosas obvias como "usar variables automáticas".


  1. Clase final : C ++ 11 proporciona el especificador final para evitar la derivación de clase
  2. C ++ 11 lambdas reducen sustancialmente la necesidad de clases de objetos con función nombrada (functor).
  3. Move Constructor : las formas mágicas en las que std :: auto_ptr funciona ya no son necesarias debido al soporte de primera clase para las referencias rvalue.
  4. Safe bool : Esto fue mencionado anteriormente. Los operadores explícitos de C ++ 11 obvian esta expresión muy común de C ++ 03.
  5. Shrink-to-fit : muchos C ++ 11 STL contienen la función de miembro shrink_to_fit() , que debería eliminar la necesidad de intercambiar con un temporal.
  6. Clase base temporal : algunas bibliotecas antiguas de C ++ utilizan esta expresión bastante compleja. Con la semántica de movimiento ya no es necesario.
  7. Las Enumeraciones Safe Enum son muy seguras en C ++ 11.
  8. Prohibir la asignación de montón : la sintaxis "= eliminar" es una forma mucho más directa de decir que una funcionalidad particular está explícitamente denegada. Esto es aplicable para evitar la asignación del montón (es decir, = eliminar para el operador miembro nuevo), evitar copias, asignación, etc.
  9. templado typedef : las plantillas de alias en C ++ 11 reducen la necesidad de typedefs con plantillas simples. Sin embargo, los generadores de tipo complejo todavía necesitan metafunciones.
  10. Algunos cálculos numéricos en tiempo de compilación, como fibonacci, se pueden reemplazar fácilmente utilizando expresiones constantes generalizadas.
  11. result_of : los usos de la plantilla de clase result_of deben reemplazarse con decltype. Creo que result_of usa decltype cuando está disponible.
  12. Los inicializadores de miembro de clase ahorran tipeo para la inicialización predeterminada de miembros no estáticos con valores predeterminados.
  13. En el nuevo código de C ++ 11 NULL debe redefinirse como nullptr pero ver la conversación de STL para saber por qué decidieron no hacerlo.
  14. Los fanáticos de la plantilla de expresión están encantados de tener la sintaxis de la función de tipo de retorno final en C ++ 11. ¡No más tipos de devolución de 30 líneas!

¡Creo que me detendré allí!


¡Tan pronto como puedas abandonar 0 y NULL a favor de nullptr , hazlo!

En código no genérico, el uso de 0 o NULL no es tan importante. Pero tan pronto como comienzas a pasar constantes de puntero nulo en el código genérico, la situación cambia rápidamente. Cuando pasa 0 a una template<class T> func(T) T se deduce como una constante de puntero nulo y no como nulo. Y no puede volver a convertirse en una constante de puntero nulo después de eso. Esto se convierte en un cenagal de problemas que simplemente no existen si el universo solo usa nullptr .

C ++ 11 no desaprueba 0 y NULL como constantes de puntero nulo. Pero debe codificar como si lo hiciera.


Cuando noté que un compilador que utiliza el estándar C ++ 11 ya no daña el siguiente código:

std::vector<std::vector<int>> a;

para supuestamente contener el operador >>, comencé a bailar. En las versiones anteriores, uno debería hacer

std::vector<std::vector<int> > a;

Para empeorar las cosas, si alguna vez tuvo que depurar esto, sabe cuán horrendos son los mensajes de error que surgen de esto.

Yo, sin embargo, no sé si esto fue "obvio" para ti.


Devolver por valor ya no es un problema. Con la semántica de movimiento y / o la optimización del valor de retorno (dependiente del compilador), las funciones de codificación son más naturales sin gastos generales ni de costo (la mayoría de las veces).


En un punto en el tiempo se argumentó que uno debe regresar por valor de const lugar de solo por valor:

const A foo(); ^^^^^

Esto fue mayormente inofensivo en C ++ 98/03, e incluso pudo haber detectado algunos errores que se veían así:

foo() = a;

Pero regresar por const está contraindicado en C ++ 11 porque inhibe la semántica del movimiento:

A a = foo(); // foo will copy into a instead of move into it

Así que solo relájate y codifica:

A foo(); // return by non-const value


No sé el nombre, pero el código C ++ 03 a menudo usaba el siguiente constructo como reemplazo de la asignación de movimiento faltante:

std::map<Big, Bigger> createBigMap(); // returns by value void example () { std::map<Big, Bigger> map; // ... some code using map createBigMap().swap(map); // cheap swap }

Esto evitó cualquier copia debido a la elisión de copia combinada con el swap anterior.


Tendrá que implementar versiones personalizadas de swap menos frecuencia. En C ++ 03, a menudo es necesario un swap eficiente sin lanzamiento para evitar copias costosas y tiradas, y dado que std::swap utiliza dos copias, el swap menudo tiene que ser personalizado. En C ++, std::swap utiliza move , por lo que el enfoque se centra en la implementación de constructores de movimiento eficientes y no lanzadores y en la transferencia de operadores de asignación. Dado que para estos el valor predeterminado es a menudo bien, esto será mucho menos trabajo que en C ++ 03.

En general, es difícil predecir qué modismos se utilizarán, ya que se crean a través de la experiencia. Podemos esperar un "C ++ 11 eficaz" tal vez el próximo año, y un "Estándar de codificación C ++ 11" solo en tres años porque la experiencia necesaria aún no está allí.


Una de las cosas que hace que evite escribir algoritmos básicos en C ++ 11 es la disponibilidad de lambdas en combinación con los algoritmos proporcionados por la biblioteca estándar.

Estoy usando esos ahora y es increíble la frecuencia con la que simplemente dices lo que quieres hacer usando count_if (), for_each () u otros algoritmos en lugar de tener que escribir los malditos bucles de nuevo.

Una vez que está utilizando un compilador C ++ 11 con una biblioteca estándar C ++ 11 completa, ya no tiene una buena excusa para no usar algoritmos estándar para construir su . Lambda solo mátalo.

¿Por qué?

En la práctica (después de haber usado esta forma de escribir algoritmos) me resulta mucho más fácil leer algo que está construido con palabras sencillas, lo que significa que se hace algo que con algunos bucles que debe desencriptar para conocer el significado. Dicho esto, hacer que los argumentos lambda se deduzcan automáticamente ayudaría mucho a hacer que la sintaxis se compare más fácilmente con un ciclo sin formato.

Básicamente, la lectura de algoritmos elaborados con algoritmos estándar es mucho más fácil que las palabras que ocultan los detalles de implementación de los bucles.

Supongo que solo se deben pensar algoritmos de nivel superior ahora que tenemos algoritmos de nivel inferior sobre los que construir.