¿Los paréntesis después del nombre del tipo marcan la diferencia con nuevo?


Si 'Test' es una clase ordinaria, ¿hay alguna diferencia entre:

Test* test = new Test;

Y

Test* test = new Test();
Author: Paul Maserrat, 2009-03-06

5 answers

Pongámonos pedantes, porque hay diferencias que en realidad pueden afectar el comportamiento de su código. Gran parte de lo siguiente está tomado de comentarios hechos a un artículo de"Old New Thing" .

A veces, la memoria devuelta por el nuevo operador se inicializará, y a veces no, dependiendo de si el tipo que está creando es un POD (datos antiguos planos), o si es una clase que contiene miembros de POD y está utilizando un valor predeterminado generado por el compilador constructor.

  • En C++1998 hay 2 tipos de inicialización: cero y por defecto
  • En C++2003 se agregó un 3er tipo de inicialización, la inicialización de valor.

Suponga:

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: {[19]]}

  • new A - valor indeterminado
  • new A() - cero inicializar

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

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

  • new C - construct por defecto (C::m es cero-inicializado)

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

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

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

  • new B - por defecto-inicializa (deja B:: m no iniciado)

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

  • new C - default: inicializa C, que llama al ctor predeterminado.

  • new C() - value-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 comportamiento entre C++98 y C++03 para el caso new B().

Esta es una de las esquinas polvorientas de C++ que te puede volver loco. Al construir un objeto, a veces quieres / necesitas los paréntesis, a veces no puedes tenerlos, y a veces no importa.

 870
Author: Michael Burr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-18 10:56:13

new Thing(); es explícito que desea que se llame a un constructor, mientras que new Thing; implica 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 a 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; vs 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é.

 51
Author: kfsone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-25 22:12:22

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.

Edit: Volver a la inicialización de los problemas con respecto a la VAINA y no POD de datos, aunque estoy de acuerdo con todo lo que ha dicho, me gustaría señalar que estos problemas sólo se aplican si la cosa está nuevo d o de lo contrario construido no tiene un constructor definido por el usuario. Si hay un constructor de este tipo se utilizará. Para el 99.99% de las clases diseñadas sensatamente habrá un constructor de este tipo, por lo que los problemas pueden ser ignorados.

 19
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-06 21:23:19

En general tenemos la inicialización por defecto en el primer caso y la inicialización por valor en el segundo caso.

Por ejemplo: en 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á valor 0.

El siguiente comportamiento dependía de su prueba de tipo. Tenemos casos diferentes: Prueba tiene constructor defult, Prueba ha generado constructor predeterminado, Prueba contiene miembro POD, no POD miembro...

 16
Author: bayda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-25 22:10:45

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

 10
Author: Evan Shaw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-06 19:59:52