Pregunta

Si 'Test' es una clase común, ¿hay alguna diferencia entre:

Test* test = new Test;

y

Test* test = new Test();
¿Fue útil?

Solución

Vayamos pedantes, porque hay diferencias que pueden afectar el comportamiento de su código. Gran parte de lo siguiente se toma de los comentarios realizados en un " Antiguo Nuevo Cosa " artículo .

Algunas veces la memoria devuelta por el nuevo operador se inicializará, y otras veces no dependiendo de si el tipo que está actualizando es un POD (datos antiguos) , o si es una clase que contiene miembros de POD y usa un constructor predeterminado generado por el compilador.

  • En C ++ 1998 hay 2 tipos de inicialización: cero y predeterminado
  • En C ++ 2003, se agregó un tercer tipo de inicialización, la inicialización del valor.

Supongamos:

struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m

En un compilador de C ++ 98, debería ocurrir lo siguiente:

  • new A - valor indeterminado
  • new A () - zero-initialize

  • new B - construcción predeterminada (B :: m no está inicializada)

  • new B () - construcción predeterminada (B :: m no está inicializada)

  • new C : construcción predeterminada (C :: m es cero inicializado)

  • new C () - construcción predeterminada (C :: m es cero inicializado)

En un compilador conforme a C ++ 03, las cosas deberían funcionar así:

  • new A - valor indeterminado
  • new A () - value-initialize A, que es una inicialización cero ya que es un POD.

  • new B : inicializa por defecto (deja B :: m sin inicializar)

  • new B () : el valor inicializa B y el cero inicializa todos los campos, ya que su ctor predeterminado es un compilador generado en lugar de definido por el usuario.

  • new C : inicializa por defecto C, que llama al ctor predeterminado.

  • new C () : el valor inicializa C, que llama al ctor predeterminado.

Así que en todas las versiones de C ++ hay una diferencia entre new A y new A () porque A es un POD.

Y hay una diferencia en el comportamiento entre C ++ 98 y C ++ 03 para el caso new B () .

Este es uno de los rincones polvorientos de C ++ que pueden volverte loco. Cuando construyes un objeto, a veces quieres o necesitas los parens, a veces no puedes tenerlos y otras no.

Otros consejos

new Thing (); es explícito de que desea que se llame a un constructor, mientras que new Thing; significa que no le importa si no se llama al constructor .

Si se usa en una estructura / clase con un constructor definido por el usuario, no hay diferencia. Si se llama en una estructura / clase trivial (por ejemplo, struct Thing {int i;}; ), entonces new Thing; es como malloc (sizeof (Thing)); mientras que new Thing (); es como calloc (sizeof (Thing)); - se inicializa con cero.

El gotcha se encuentra en el medio:

struct Thingy {
  ~Thingy(); // No-longer a trivial class
  virtual WaxOn();
  int i;
};

El comportamiento de new Thingy; frente a new Thingy (); en este caso cambió entre C ++ 98 y C ++ 2003. Vea la explicación de Michael Burr sobre cómo y por qué.

No, son lo mismo. Pero hay una diferencia entre:

Test t;      // create a Test called t

y

Test t();   // declare a function called t which returns a Test

Esto se debe a la regla básica de C ++ (y C): si algo puede ser una declaración, entonces es una declaración.

Editar: Con respecto a los problemas de inicialización con respecto a los datos POD y no POD, aunque estoy de acuerdo con todo lo que se ha dicho, me gustaría señalar que estos problemas solo se aplican si new'd o construido de otra manera no tiene un constructor definido por el usuario. Si existe tal constructor será utilizado. Para el 99,99% de las clases diseñadas sensiblemente, habrá un constructor de este tipo, por lo que los problemas se pueden ignorar.

En general, tenemos inicialización predeterminada en el primer caso e inicialización de valor en el segundo caso.

Por ejemplo: en el caso de int (tipo POD):

  • int * test = new int : tenemos cualquier inicialización y el valor de * test puede ser cualquiera.

  • int * test = new int () - * la prueba tendrá un valor de 0.

El siguiente comportamiento depende de tu tipo Test. Tenemos diferentes casos: la prueba tiene constructor defectuoso, la prueba ha generado el constructor predeterminado, la prueba contiene miembro POD, no miembro POD ...

Suponiendo que Test es una clase con un constructor definido, no hay diferencia. La última forma deja un poco más claro que el constructor de Test se está ejecutando, pero eso es todo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top