Con el nuevo estándar, hay nuevas formas de hacer las cosas, y muchas son más agradables que las viejas, pero la vieja forma todavía está bien. También está claro que el nuevo estándar no se desprecia oficialmente mucho, 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 de C ++ 11, y qué podemos hacer ahora en su lugar?
Al responder esto, puede omitir las cosas obvias como "usar variables automáticas".

auto_ptr, también está en desuso.Respuestas:
finalespecificador para evitar la derivación de clasestd::auto_ptrobras ya no son necesarias debido al soporte de primera clase para las referencias de valor.shrink_to_fit()función miembro, que debería eliminar la necesidad de intercambiar por una temporal.= deletesintaxis es una forma mucho más directa de decir que una funcionalidad particular se niega explícitamente. Esto es aplicable para evitar la asignación del montón (es decir,=deletepara el miembrooperator new), evitar copias, asignación, etc.result_of: Los usos de la plantilla de claseresult_ofdeben reemplazarse pordecltype. Creo queresult_ofusadecltypecuando está disponible.NULLdebe redefinirse comonullptr, pero vea la charla de STL para saber por qué decidieron no hacerlo.¡Creo que me detendré allí!
fuente
result_ofde la lista. A pesar de lo engorroso que setypenamenecesitaba antes, creo que atypename result_of<F(Args...)::typeveces puede ser más fácil de leer quedecltype(std::declval<F>()(std::declval<Args>()...), y con la aceptación de N3436 en el documento de trabajo, ambos trabajan para SFINAE (que solía ser una ventaja de lodecltypequeresult_ofno ofrecía)En un momento dado se argumentó que uno debería regresar por
constvalor en lugar de solo por valor:Esto fue mayormente inofensivo en C ++ 98/03, e incluso puede haber detectado algunos errores que parecían:
Pero regresar
constestá contraindicado en C ++ 11 porque inhibe la semántica del movimiento:Así que relájate y codifica:
fuente
A& operator=(A o)&lugar deA& operator=(A o). Estos evitan los errores tontos y hacen que las clases se comporten más como los tipos básicos y no evitan la semántica de movimiento.¡Tan pronto como pueda abandonar
0yNULLen favornullptr, hágalo!En el código no genérico, el uso de
0oNULLno es tan importante. Pero tan pronto como comience a pasar constantes de puntero nulo en código genérico, la situación cambia rápidamente. Cuando pasa0a untemplate<class T> func(T)Tse deduce como uninty no como un puntero nulo constante. Y no se puede convertir de nuevo a un puntero nulo constante después de eso. Esto cae en un atolladero de problemas que simplemente no existen si el universo solo se usanullptr.C ++ 11 no se desprecia
0yNULLcomo constantes de puntero nulo. Pero debe codificar como si lo hiciera.fuente
std::nullptr_t.0oNULLpara punteros nulos").Safe bool idiom →
explicit operator bool().Constructores de copia privada (boost :: noncopyable) →
X(const X&) = deleteSimulando la clase final con destructor privado y herencia virtual →
class X finalfuente
Una de las cosas que simplemente 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.
Los estoy usando ahora y es increíble la frecuencia con la que dices lo que quieres hacer usando count_if (), for_each () u otros algoritmos en lugar de tener que volver a escribir los malditos bucles.
Una vez que está utilizando un compilador de C ++ 11 con una biblioteca estándar completa de C ++ 11, ya no tiene una buena excusa para no usar algoritmos estándar para construir su propio . Lambda acaba de matarlo.
¿Por qué?
En la práctica (después de haber utilizado esta forma de escribir algoritmos yo mismo), es mucho más fácil leer algo que está construido con palabras sencillas que significan lo que se hace que con algunos bucles que hay que descifrar para saber el significado. Dicho esto, hacer que los argumentos lambda se deduzcan automáticamente ayudaría mucho a que la sintaxis sea más fácilmente comparable a un bucle sin formato.
Básicamente, los algoritmos de lectura hechos con algoritmos estándar son mucho más fáciles ya que las palabras ocultan los detalles de implementación de los bucles.
Supongo que solo debemos pensar en algoritmos de nivel superior ahora que tenemos algoritmos de nivel inferior para construir.
fuente
for_eachcon un lambda sea mejor que el bucle for basado en rango equivalente, con el contenido del lambda en el bucle. El código se ve más o menos igual, pero la lambda introduce algunos signos de puntuación adicionales. Puede usar equivalentes de cosas comoboost::irangeaplicarlo a más bucles que solo aquellos que obviamente usan iteradores. Además, el bucle for basado en rango tiene una mayor flexibilidad, ya que puede salir temprano si es necesario (porreturno porbreak), mientras que con lafor_eachnecesidad de lanzar.forhace que elit = c.begin(), const end = c.end(); it != end; ++itidioma habitual desaparezca.for_eachalgoritmo sobre el rango basado en el bucle es que no puedebreako noreturn. Es decir, cuando vesfor_eachque sabes de inmediato sin mirar el cuerpo que no hay tal engaño.std::for_each(v.begin(), v.end(), [](int &i) { ++i; });confor (auto &i : v) { ++i; }. Acepto que la flexibilidad es de doble filo (gotoes muy flexible, ese es el problema). No creo que la limitación de no poder utilizarbreaken losfor_eachcompensa de versión para el nivel de detalle adicional que exige - usuarios defor_eachaquí están sacrificando la OMI lectura real y conveniencia con una especie de noción teórica de que elfor_eaches , en principio, más clara y conceptualmente más simple En la práctica no es más claro ni más simple.Deberá implementar versiones personalizadas con
swapmenos frecuencia. En C ++ 03, aswapmenudo es necesario un no-lanzamiento eficiente para evitar costosas y tirar copias, y dado questd::swapusa dos copias, aswapmenudo tiene que ser personalizado. En C ++,std::swaputilizamove, y por lo tanto, el enfoque cambia en la implementación de constructores de movimientos y operadores de asignación de movimientos eficientes y no arrojables. Dado que para estos el valor predeterminado es a menudo correcto, será mucho menos trabajo que en C ++ 03.En general, es difícil predecir qué expresiones idiomáticas se utilizarán, ya que se crean a través de la experiencia. Podemos esperar un "C ++ 11 efectivo" tal vez el próximo año, y un "Estándares de codificación C ++ 11" solo en tres años porque la experiencia necesaria aún no existe.
fuente
No sé el nombre, pero el código C ++ 03 a menudo usaba la siguiente construcción como reemplazo de la asignación de movimiento faltante:
Esto evitó cualquier copia debido a la elisión de copia combinada con lo
swapanterior.fuente
maptodos modos. La técnica que muestra es útil simapya existe, en lugar de simplemente ser construida. El ejemplo sería mejor sin el comentario de "constructor predeterminado barato" y con "// ..." entre esa construcción y el intercambioCuando noté que un compilador que usa el estándar C ++ 11 ya no falla el siguiente código:
por supuestamente contener operador >>, comencé a bailar. En las versiones anteriores habría que hacer
Para empeorar las cosas, si alguna vez tuvo que depurar esto, ya sabe lo horrendos que son los mensajes de error que salen de esto.
Yo, sin embargo, no sé si esto fue "obvio" para usted.
fuente
El retorno 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 o costos (la mayoría de las veces).
fuente