Os parênteses após o nome do tipo fazem diferença com o novo?

Se ‘Teste’ é uma class comum, existe alguma diferença entre:

Test* test = new Test; 

e

 Test* test = new Test(); 

Vamos ficar pedantes, porque existem diferenças que podem realmente afetar o comportamento do seu código. Muito do que se segue é retirado de comentários feitos a um artigo “Old New Thing” .

Às vezes, a memory retornada pelo novo operador será inicializada e, às vezes, não dependerá se o tipo que você está criando for POD (plain old data) , ou se for uma class que contenha membros POD e estiver usando um construtor padrão gerado pelo compilador.

  • Em C ++ 1998 existem 2 tipos de boot: zero e padrão
  • Em C ++ 2003, um terceiro tipo de boot, a boot do valor foi adicionada.

Assumir:

 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 

Em um compilador C ++ 98, o seguinte deve ocorrer:

  • new A – valor indeterminado
  • new A() – inicializar zero

  • new B – construto padrão (B :: m não é inicializado)

  • new B() – construção padrão (B :: m não é inicializado)

  • new C – default construct (C :: m é inicializado com zero)

  • new C() – construção padrão (C :: m é inicializado com zero)

Em um compilador em conformidade com o C ++ 03, as coisas devem funcionar da seguinte forma:

  • new A – valor indeterminado
  • new A() – inicializa o valor A, que é zero-boot, já que é um POD.

  • new B – default-initializes (deixa B :: m não inicializado)

  • new B() – valor-inicializa B que inicializa zero todos os campos desde que seu ctor padrão é compilador gerado ao contrário de definido pelo usuário.

  • new C – default-initializa C, que chama o ctor padrão.

  • new C() – valor inicializa C, que chama o ctor padrão.

Portanto, em todas as versões do C ++ há uma diferença entre o new A e o new A() porque A é um POD.

E há uma diferença no comportamento entre C ++ 98 e C ++ 03 para o caso new B() .

Este é um dos cantos empoeirados do C ++ que pode deixá-lo louco. Ao construir um object, às vezes você quer / precisa dos parênteses, às vezes você absolutamente não pode tê-los, e às vezes isso não importa.

new Thing(); é explícito que você quer um construtor chamado enquanto new Thing; é levado a implicar que você não se importa se o construtor não é chamado.

Se usado em uma struct / class com um construtor definido pelo usuário, não há diferença. Se chamado em uma estrutura / class trivial (por exemplo, struct Thing { int i; }; ) então new Thing; é como malloc(sizeof(Thing)); que new Thing(); é como calloc(sizeof(Thing)); – fica zero inicializado.

A pegadinha está no meio:

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

O comportamento do new Thingy; vs new Thingy(); neste caso, mudou entre C ++ 98 e C ++ 2003. Veja a explicação de Michael Burr para como e por quê.

Não, eles são iguais. Mas há uma diferença entre:

 Test t; // create a Test called t 

e

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

Isso ocorre por causa da regra básica de C ++ (e C): se algo puder ser uma declaração, então é uma declaração.

Edit: Re os problemas de boot sobre POD e não-POD dados, enquanto eu concordo com tudo o que foi dito, gostaria apenas de salientar que estas questões só se aplicam se a coisa que está sendo nova ou de outra forma construída não tem um construtor definido pelo usuário. Se houver tal construtor, será usado. Para 99,99% das classs projetadas de forma sensata, haverá um construtor desse tipo e, portanto, os problemas podem ser ignorados.

Em geral, temos a boot padrão no primeiro caso e a boot do valor no segundo caso.

Por exemplo: no caso com int (tipo POD):

  • int* test = new int – temos qualquer boot e valor de * test pode ser qualquer.

  • int* test = new int() – * teste terá valor 0.

O próximo comportamento dependeu do seu tipo Test. Temos casos diferentes: o teste tem o construtor defult, o teste gerou o construtor padrão, o teste contém o membro POD, o membro não POD …

Assumindo que Test é uma class com um construtor definido, não há diferença. A última forma torna um pouco mais claro que o construtor do Teste está sendo executado, mas é sobre isso.