Pregunta ¿Los paréntesis después del nombre de tipo marcan la diferencia con los nuevos?


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

Test* test = new Test;

y

Test* test = new Test();

891
2018-03-06 19:39


origen


Respuestas:


Vamos a ser pedantes, porque hay diferencias que realmente pueden afectar el comportamiento de tu código. Gran parte de lo siguiente se toma de los comentarios hechos a un Artículo "Old New Thing".

A veces, la memoria devuelta por el nuevo operador se inicializará, y algunas veces no dependerá de si el tipo que estás renovando es un POD (datos antiguos simples), o si es una clase que contiene miembros POD y está utilizando un constructor predeterminado generado por el compilador.

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

Asumir:

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 C ++ 98, lo siguiente debería ocurrir:

  • new A   - valor indeterminado
  • new A() - cero inicialización

  • 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 tiene cero inicialización)

  • new C() - construcción predeterminada (C :: m tiene cero inicialización)

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

  • new A    - valor indeterminado
  • new A()  - value-initialize A, que es cero-initialization ya que es un POD.

  • new B    - default-initializes (deja B :: m sin inicializar)

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

  • new C    - Inicializa por defecto C, que llama al ctor predeterminado.

  • new C()  - value-initializes C, que llama al ctor predeterminado.

Entonces, 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 puede volverte loco. Cuando construyes un objeto, a veces quieres / necesitas los parens, a veces no puedes tenerlos, y a veces no importa.


860
2018-03-06 21:01



new Thing(); es explícito que quieres un constructor llamado mientras new Thing; se toma para dar a entender que no te 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 invoca una estructura / clase trivial (p. struct Thing { int i; };) entonces new Thing; es como malloc(sizeof(Thing)); mientras new Thing(); es como calloc(sizeof(Thing)); - se inicializa 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é.


49
2018-02-15 19:57



No ellos son los mismos. 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: 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 lo que se está creando o construyendo no tiene un usuario. constructor definido Si existe tal constructor, se usará. Para el 99,99% de las clases diseñadas con sensatez, habrá tal constructor, por lo que los problemas se pueden ignorar.


16
2018-03-06 19:42



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

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

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

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

el siguiente comportamiento depende de su tipo Prueba. Tenemos casos diferentes: la prueba tiene un constructor de fallas, la prueba ha generado el constructor predeterminado, la prueba contiene el miembro POD, el miembro no POD ...


16
2018-03-06 20:00



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


10
2018-03-06 19:42