He estado usando la nueva autopalabra clave disponible en el estándar C ++ 11 para tipos de plantillas complicados, para lo cual creo que fue diseñada. Pero también lo estoy usando para cosas como:
auto foo = std::make_shared<Foo>();
Y más escépticamente por:
auto foo = bla(); // where bla() return a shared_ptr<Foo>
No he visto mucha discusión sobre este tema. Parece que autopodría usarse en exceso, ya que un tipo es a menudo una forma de documentación y controles de sanidad. ¿Dónde trazas la línea de uso autoy cuáles son los casos de uso recomendados para esta nueva característica?
Para aclarar: no estoy pidiendo una opinión filosófica; Solicito el uso previsto de esta palabra clave por parte del comité estándar, posiblemente con comentarios sobre cómo se realiza ese uso previsto en la práctica.
Nota al margen: esta pregunta se trasladó a SE.Programmers y luego a Stack Overflow. La discusión sobre esto se puede encontrar en esta meta pregunta .

autopalabra clave, entonces sabes cómo se supone que debe usarse. Eso es lo que pregunto, como alguien que es nuevo en esta función, ¿cómo se supone que debo usarla?var(es decir, una vez que la gente superó la idea de que no era una escritura dinámica después de todo). Si lo desea, puede comenzar con esta pregunta y pasar por las preguntas relacionadas.auto foo = bla();"malo" es claramente una opinión, no un hecho, lo que hace esta pregunta y responde a una discusión, lo que la hace relevante para los Programadores SE, que es exactamente lo que indican los votos cerrados. / encogimiento de hombrosRespuestas:
Creo que uno debe usar la
autopalabra clave siempre que sea difícil decir cómo escribir el tipo a primera vista, pero el tipo del lado derecho de una expresión es obvio. Por ejemplo, usando:para obtener el tipo de clave compuesta
boost::multi_index, aunque sepa que es asíint. No puedes simplemente escribirintporque podría cambiarse en el futuro. Yo escribiríaautoen este caso.Entonces, si la
autopalabra clave mejora la legibilidad en un caso particular, úsela. Puede escribirautocuando sea obvio para el lector qué tipoautorepresenta.Aquí hay unos ejemplos:
fuente
bla()regrese se lo estás dandofoo.Úselo
autodonde pueda, especialmenteconst autopara que los efectos secundarios sean menos preocupantes. No tendrá que preocuparse por los tipos, excepto en los casos obvios, pero todavía serán verificados estáticamente por usted y puede evitar algunas repeticiones. Dondeautono sea factible, puede usarlodecltypepara expresar tipos semánticamente como contratos basados en expresiones. Su código se verá diferente, pero será un cambio positivo.fuente
auto&&en situaciones complejas edmundv.home.xs4all.nl/blog/2014/01/28/…const auto&o, aconst automenos que explícitamente, quiera mutar o mover.auto str = std::string();lugar destd::string str;?Fácil. Úselo cuando no le importa cuál es el tipo. Por ejemplo
Todo lo que me importa aquí es que
isea lo que haya en el contenedor.Es un poco como typedefs.
En este caso, no me importa si
hywson flotadores o dobles, sólo que son cualquier tipo es adecuado para expresar alturas y pesos .O considerar
Aquí todo lo que me importa es que es un iterador adecuado, compatible
operator++(), es como escribir un pato a este respecto.Además, el tipo de lambdas no se puede deletrear, por lo que
auto f = []...es un buen estilo. La alternativa es emitirstd::functionpero eso viene con gastos generales.Realmente no puedo concebir un "abuso" de
auto. Lo más cercano que puedo imaginar es privarte de una conversión explícita a algún tipo significativo, pero no lo usaríasautopara eso, construirías un objeto del tipo deseado.Si puede eliminar algo de redundancia en su código sin introducir efectos secundarios, entonces debe ser bueno hacerlo.
Contraejemplos (tomados de las respuestas de otra persona):
Aquí nos importa cuál es el tipo, por lo que debemos escribir
Someclass i;yfor(unsigned x = y;...fuente
auto.Ve a por ello. Úselo en
autocualquier lugar que facilite la escritura de código.Cada nueva característica en cualquier idioma será utilizada en exceso por al menos algunos tipos de programadores. Es solo a través del uso excesivo moderado por algunos programadores experimentados (no novatos) que el resto de los programadores experimentados aprenden los límites del uso adecuado. El uso excesivo extremo suele ser malo, pero podría ser bueno porque dicho uso excesivo puede conducir a mejoras en la función o una mejor función para reemplazarla.
Pero si estuviera trabajando en código con más de unas pocas líneas como
donde el tipo se indica cero veces, es posible que desee cambiar esas líneas para incluir tipos. El primer ejemplo es excelente ya que el tipo se indica una vez y
autonos ahorra tener que escribir dos tipos de plantillas desordenadas. ¡Hurra por C ++++! Pero mostrar explícitamente el tipo cero veces, si no es fácilmente visible en una línea cercana, me pone nervioso, al menos en C ++ y sus sucesores inmediatos. Para otros lenguajes diseñados para trabajar en un nivel superior con más abstracción, polimorfismo y genérico, está bien.fuente
En C ++ y más allá de 2012 en el panel Ask Us Anything , hubo un intercambio fantástico entre Andrei Alexandrescu, Scott Meyers y Herb Sutter hablando sobre cuándo usar y no usar
auto. Pase al minuto 25:03 para una discusión de 4 minutos. Los tres altavoces ofrecen excelentes puntos que deben tenerse en cuenta para cuándo no usarauto.Recomiendo encarecidamente a las personas que lleguen a su propia conclusión, pero mi objetivo fue usarlo en
autotodas partes a menos que :El uso liberal de
explicitayuda a reducir la preocupación por el segundo, lo que ayuda a minimizar la cantidad de tiempo que el primero es un problema.Reformulando lo que dijo Herb, "si no estás haciendo X, Y y Z, usa
auto. Aprende qué son X, Y y Z y ve y usa enautotodas partes".fuente
Sí, se puede usar en exceso en detrimento de la legibilidad. Sugiero usarlo en los contextos donde los tipos exactos son largos, indescifrables o no importantes para la legibilidad, y las variables son de corta duración. Por ejemplo, el tipo de iterador generalmente es largo y no es importante, por
autolo que funcionaría:autoaquí no hace daño a la legibilidad.Otro ejemplo es el tipo de regla del analizador, que puede ser largo y complicado. Comparar:
con
Por otro lado, cuando se conoce el tipo y es simple, es mucho mejor si declara explícitamente:
más bien que
fuente
begin()yend(), o el tamaño de tu paso es diferente a uno, o estás modificando el contenedor a medida que avanzas, la declaración basada en el rango no te ayudará.r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&>hace?spacees y buscarlo. Esa es la información más útil de todos modos ... después de todo, el problema no es "¿qué tipo es esta nueva variable" sino más bien "quéspace & space & spacesignifica?" El tipo real de la expresión es solo ruido.autopuede ser muy peligroso en combinación con plantillas de expresión que se usan mucho en bibliotecas de álgebra lineal como Eigen u OpenCV.Los errores causados por este tipo de errores son un gran dolor para depurar. Un posible remedio es emitir explícitamente el resultado al tipo esperado si está empeñado en usar auto para el estilo de declaración de izquierda a derecha.
fuente
A*Bexpresión se copie o no en unaautovariable o en otra cosa, el comportamiento que usted describe sigue presente.auto.diag(A * B), no tiene que desperdiciar ciclos calculando los elementos fuera de la diagonal.Utilizo
autosin restricción y no tuve ningún problema. Incluso a veces termino usándolo para tipos simples comoint. Esto hace que c ++ sea un lenguaje de nivel superior para mí, y permite declarar variables en c ++ como en python. Después de escribir el código de Python, incluso a veces escribo, por ejemploen vez de
Este es un caso en el que diría que es un abuso de la
autopalabra clave.A menudo no me importa cuál es el tipo exacto del objeto, estoy más interesado en su funcionalidad, y como los nombres de las funciones generalmente dicen algo sobre los objetos que devuelven,
autono duele: por ejemploauto s = mycollection.size(), puedo suponer quesserá una especie de número entero, y en el raro caso en que me preocupe el tipo exacto, verifiquemos el prototipo de la función (quiero decir, prefiero tener que verificar cuando necesito la información, en lugar de a priori cuando se escribe el código, solo en caso de que sea útil algún día, como enint_type s = mycollection.size()).Con respecto a este ejemplo de la respuesta aceptada:
En mi código todavía lo uso
autoen este caso, y si quieroxestar sin firmar, entonces uso una función de utilidad, llamada saymake_unsigned, que expresa claramente mis preocupaciones:Descargo de responsabilidad: ¡acabo de describir mi uso, no soy competente para dar consejos!
fuente
auto i = MyClass().as_unsignedse recomienda allí, o inclusoauto w = widget{};.Uno de los principales problemas con el programa C ++ es que le permite usar la variable no inicializada . Esto nos lleva a un comportamiento desagradable del programa no determinista. Cabe señalar que el compilador moderno ahora arroja mensajes de advertencia apropiados / mensaje si el programa se cansa de usarlo.
Solo para ilustrar esto, considere el siguiente programa c ++:
Si compilo este programa usando el compilador moderno (GCC), me da la advertencia. Tal advertencia puede no ser muy obvia si estamos trabajando con el código de producción complejo real.
================================================== =============================== Ahora si cambiamos nuestro programa que usa auto , compilamos y obtenemos lo siguiente:
Con auto, no es posible usar la variable no inicializada. Esta es una gran ventaja que podemos obtener (gratis), si comenzamos a usar auto .
Este concepto y otro gran gran concepto moderno de C ++ es explicado por Herb Shutter, experto en C ++, en su charla CppCon14 :
¡De vuelta a lo basico! Elementos esenciales del estilo moderno de C ++
fuente
auto.auto, pero no lo necesita para abordar este problema.Un peligro que he notado es en términos de referencias. p.ej
El problema es que another_ref no es realmente una referencia en este caso, es MyBigObject en lugar de MyBigObject &. Terminas copiando un objeto grande sin darte cuenta.
Si obtiene una referencia directamente de un método, es posible que no piense en qué es realmente.
necesitaría "auto &" o "const auto &"
fuente
Use
autodonde tenga sentido que se infiera un tipo. Si tiene algo que sabe que es un número entero, o sabe que es una cadena, simplemente use int / std :: string, etc. No me preocuparía por "usar en exceso" una característica del lenguaje a menos que llegue al punto de ridículo, u ofusca el código.Esa es mi opinión de todos modos.
fuente
autoLa palabra clave solo se puede usar para variables locales, no para argumentos o miembros de clase / estructura. Por lo tanto, es seguro y viable usarlos en cualquier lugar que desee. Los uso mucho. El tipo se deduce en el momento de la compilación, el depurador muestra el tipo durante la depuración, losizeofinforma correctamente,decltypedaría el tipo correcto, no hay daño. ¡No cuentoautocomo sobreutilizado, nunca!fuente
TL; DR: Vea la regla general en la parte inferior.
La respuesta aceptada sugiere la siguiente regla general:
Pero yo diría que es demasiado restrictivo. A veces no me importan los tipos, ya que la declaración es lo suficientemente informativa sin que me moleste en tomarme el tiempo para resolver el tipo. ¿Qué quiero decir con eso? Considere el ejemplo que ha aparecido en algunas de las respuestas:
¿Qué hace de esto un ejemplo de mal uso de
auto? ¿Es mi ignorancia delf()tipo de retorno de? Bueno, de hecho puede ayudar si lo supiera, pero esa no es mi principal preocupación. Lo que es un problema mucho mayor es esoxy nof()tienen mucho sentido. Si tuvieramos:en cambio, generalmente no me importa si el tipo de retorno de la función es obvio o no. Al leer la declaración, sé lo que estoy haciendo y sé lo suficiente sobre la semántica del valor de retorno para no sentir que necesito saber también su tipo.
Entonces mi respuesta es: usar
autosiempre que el compilador lo permita, a menos que:Y también:
autopor el tipo concreto.fuente
Una de mis amargas experiencias
autoes usarlo con expresiones lambda :En realidad, aquí
ise resuelve funcionar el puntero deint(*)(). Esto es simplecout, pero imagínese qué tipo de errores de compilación / tiempo de ejecución incorrectos puede causar cuando se usatemplate.Debe evitar
autocon tales expresiones y poner unreturntipo apropiado (o controladodecltype())El uso correcto para el ejemplo anterior sería,
fuente
()al final. Las lambdas están ahí para actuar como funciones y de ahí proviene la conversión del puntero de función. Si quieres llamarlo de inmediato, ¿por qué usar una lambda?auto i = 0;Funciona bastante bien.auto x = []() { /* .... whatever goes in here ... */ }()es mejor queauto x = /* .... whatever goes in here ... */;, es decir, lo mismo, sin la lambda? Me parece bastante inútil, por la misma razón noauto x = 42 + y - 42tiene sentido.