¿Cuál es la diferencia entre Object obj = Object() y Object obj()?

5 minutos de lectura

avatar de usuario
Denis Sologub

Creo que tiene mucha información al respecto, pero no sé cómo se llama esto. No puedo entender la diferencia entre las siguientes dos cadenas de código:

Object obj();

Y

Object obj = Object();

¿Puede usted explicar por favor? O al menos decir cómo llamarlo.

  • Bien, ¿por qué entonces tengo un problema cuando uso Object obj() pero no entiendo cuando se usa Object obj = Object()?

    – Denis Sologub

    21 de diciembre de 2015 a las 20:09

  • @ghostman bueno, deberías estar usando Object obj;sin los paréntesis

    – dabadaba

    21 de diciembre de 2015 a las 20:10


  • @juanchopanza ahora que me fijé en los paréntesis tienes razón, son diferentes. Supuse que OP dijo Object objno Object obj().

    – dabadaba

    21 de diciembre de 2015 a las 20:13

avatar de usuario
vladon

Object obj();

no es una instanciación del objeto, es un declaración de una función obj que no toma argumentos y devuelve una instancia de Object.

Object obj;

es un default initializationes decir, creación de instancias con constructor implícito (por lo tanto, constructor implícito predeterminado o no definido por el usuario).explicit constructor sin parámetros), y esta declaración llama a constructores implícitos de no POD Object miembros, y para los tipos POD no los inicializa (no se pondrán a cero). Esto es correcto para miembros de miembros de Object y así sucesivamente recursivamente.

Object obj{};

es un inicialización de lista o inicialización agregada (si Object es un agregado). Aquellos a los que llamó de manera diferente, para llaves vacías, el comportamiento es el mismo: todos los miembros de los tipos POD se inicializan en cero y los que no son POD se inicializan por defecto.

Object obj = Object();

teóricamente es una declaración de dos pasos: 1) crear temporal Object instancia; 2) luego construya obj mediante el constructor de copia/constructor de movimiento/operador de copia/operador de movimiento. Pero en la práctica, se construirá de forma predeterminada teniendo en cuenta la elisión de copiar/mover (está habilitado en todos los compiladores modernos de forma predeterminada, incluso con todas las optimizaciones desactivadas, debe deshabilitar la elisión explícitamente). Mejor no uses esta variante.

Preconclusión

Elegir

Object obj;

o

Object obj{};

Elija primero si desea una inicialización rápida sin poner a cero sus miembros POD. Elija el segundo si quiere estar seguro de que todos sus miembros POD serán cero después de la instanciación de Object.

Prácticamente, antes de la primera lectura de sus miembros, ambas variantes tienen la misma velocidad en tiempo de ejecución en todos los sistemas operativos modernos.

Asi que…

Conclusión

Utilice la inicialización de valor:

Object obj{};

a menos que necesite un rendimiento en tiempo real en sistemas exóticos.

  • debe tener en cuenta que Object obj{}; es una característica de C++11 y no estaba disponible en versiones anteriores. He tenido que lidiar con esto regularmente, ya que parte de nuestro código fuente es compartido por otro equipo que, por razones técnicas, todavía usa C++ 09, por lo que los archivos comunes a ambos proyectos no pueden usar esta notación.

    – Darrel Hoffmann

    22 de diciembre de 2015 a las 15:54

  • @DarrelHoffman ¡Vamos, hoy termina el 2015! C++14 ES un estándar, C++17 viene.

    – vladon

    22 de diciembre de 2015 a las 15:56

  • No cambia el hecho de que muchas empresas siguen utilizando los estándares más antiguos. El OP usó la etiqueta C++ y no las etiquetas C++11 (o posterior), por lo que no puede asumir que están usando el último estándar.

    – Darrel Hoffmann

    22 de diciembre de 2015 a las 15:58


  • @DarrelHoffman ¿Por qué no recuerda Borland Turbo C++ para DOS entonces? Muchas empresas están inundadas de ancianos llamados programadores que simplemente no quieren aprender nada nuevo. He conocido a muchos de esos. Eso es muy malo. También he conocido a varias empresas modernas que usan C++ al borde de los nuevos estándares en producción (incluso para sistemas integrados). Y son los mejores.

    – vladon

    22 de diciembre de 2015 a las 16:07

  • @vladon: Hay muchos gastos generales en términos de costos de cambio, y muchas empresas todavía se ven obligadas por una variedad de razones a trabajar con código heredado. Claro, si fuera por mí, usaría lo último y lo mejor de todo, pero no siempre tenemos la opción de hacerlo, especialmente en las empresas más grandes que existen desde hace más de una década. Me he metido en problemas más de una vez por usar código de estilo C++ 11 que funciona en mi proyecto pero no compila para otros equipos que usan los mismos archivos con compiladores más antiguos. Solo quería señalar que no todos tienen esa opción.

    – Darrel Hoffmann

    22 de diciembre de 2015 a las 16:19

Object obj();

declara una función, no un objeto! Esta es una instancia del “Análisis más desconcertante”.

Object obj = Object();

requiere Object tener un constructor de movimiento o un constructor de copia accesible (aunque el compilador podría terminar eliminando el movimiento/copia).

Las formas simples de crear un objeto incluyen:

Object obj;
Object obj{};

  • ¡Gracias! Lo entendí, no lo sé.

    – Denis Sologub

    21 de diciembre de 2015 a las 20:11


  • Object obj; y Object obj{}; son diferentes.

    – vladon

    21 dic 2015 a las 20:40

avatar de usuario
NathanOliver

Object obj();

Declara los nombres de una función obj que devuelve un Object y no toma parámetros. Esto generalmente no es lo que quieres.

Object obj = Object();

declara un Object nombrada obj luego se inicializa la copia con un valor predeterminado temporal construido Object. Normalmente, tampoco desea hacer esto a menos que esté restableciendo un objeto a un estado predeterminado.

En general, si desea construir sin llamar a un constructor, puede usar

Object obj;
//or
Object obj{};

  • ¡Gracias por la respuesta avanzada!

    – Denis Sologub

    21 de diciembre de 2015 a las 20:13

  • Object obj{}; es la iniciación del valor, no la inicialización predeterminada. Eso puede marcar la diferencia en algunos casos.

    – juanchopanza

    21 de diciembre de 2015 a las 20:32

Gran diferencia.

El primero es un prototipo de función para una función que no toma argumentos y devuelve un Objeto.

El segundo instancia un objeto llamando al constructor predeterminado. Para evitar dudas, no se llama al operador de asignación.

Elimina los paréntesis en el primer caso para que las declaraciones sean equivalentes.

¿Ha sido útil esta solución?