Domanda

Se 'Test' è una classe normale, c'è qualche differenza tra:

Test* test = new Test;

e

Test* test = new Test();
È stato utile?

Soluzione

Diventiamo pedanti, perché ci sono differenze che possono effettivamente influenzare il comportamento del tuo codice. Gran parte di quanto segue è tratto dai commenti fatti a un " Vecchio Nuovo cosa " articolo .

A volte la memoria restituita dal nuovo operatore viene inizializzata, a volte non dipende dal fatto che il tipo di cui stai eseguendo il nuovo aggiornamento sia POD (semplici vecchi dati) , o se si tratta di una classe che contiene membri POD e utilizza un costruttore predefinito generato dal compilatore.

  • In C ++ 1998 ci sono 2 tipi di inizializzazione: zero e default
  • In C ++ 2003 è stato aggiunto un terzo tipo di inizializzazione, inizializzazione del valore.

Si supponga:

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

In un compilatore C ++ 98, dovrebbe verificarsi quanto segue:

  • new A - valore indeterminato
  • new A () - zero-inizializza

  • new B - costrutto predefinito (B :: m non è inizializzato)

  • new B () - costrutto predefinito (B :: m non è inizializzato)

  • new C - costrutto predefinito (C :: m è zero inizializzato)

  • new C () - costrutto predefinito (C :: m è zero inizializzato)

In un compilatore conforme a C ++ 03, le cose dovrebbero funzionare così:

  • new A - valore indeterminato
  • new A () - valore-inizializza A, che è inizializzazione zero poiché è un POD.

  • new B - default-initializes (lascia B :: m non inizializzato)

  • new B () - inizializza valore B che azzera tutti i campi poiché il suo ctor predefinito è generato dal compilatore anziché definito dall'utente.

  • new C - default-inizializza C, che chiama il ctor predefinito.

  • new C () - value-inizializza C, che chiama il ctor predefinito.

Quindi in tutte le versioni di C ++ c'è una differenza tra new A e new A () perché A è un POD.

E c'è una differenza nel comportamento tra C ++ 98 e C ++ 03 per il caso new B () .

Questo è uno degli angoli polverosi del C ++ che può farti impazzire. Quando costruisci un oggetto, a volte vuoi / hai bisogno dei genitori, a volte non puoi assolutamente averli, a volte non importa.

Altri suggerimenti

new Thing (); è esplicito che vuoi che venga chiamato un costruttore mentre new Thing; è implicito nel senso che non ti dispiace se il costruttore non viene chiamato .

Se utilizzato su una struttura / classe con un costruttore definito dall'utente, non vi è alcuna differenza. Se chiamato su una struttura / classe banale (es. struct Thing {int i;}; ) allora new Thing; è come malloc (sizeof (Thing)); considerando che new Thing (); è come calloc (sizeof (Thing)); - viene inizializzato zero.

Il gotcha si trova nel mezzo:

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

Il comportamento di new Thingy; vs new Thingy (); in questo caso è cambiato tra C ++ 98 e C ++ 2003. Vedi la spiegazione di Michael Burr per come e perché.

No, sono uguali. Ma c'è una differenza tra:

Test t;      // create a Test called t

e

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

Ciò è dovuto alla regola di base C ++ (e C): se qualcosa può essere una dichiarazione, allora è una dichiarazione.

Modifica: riguardo ai problemi di inizializzazione relativi ai dati POD e non POD, mentre sono d'accordo con tutto ciò che è stato detto, vorrei solo sottolineare che questi problemi si applicano solo se new'd o altrimenti costruito non ha un costruttore definito dall'utente. Se esiste un tale costruttore, verrà utilizzato. Per il 99,99% delle classi progettate in modo ragionevole ci sarà un tale costruttore, e quindi i problemi possono essere ignorati.

In generale abbiamo l'inizializzazione predefinita nel primo caso e l'inizializzazione del valore nel secondo caso.

Ad esempio: nel caso con int (tipo POD):

  • int * test = new int - abbiamo qualsiasi inizializzazione e il valore di * test può essere qualsiasi.

  • int * test = new int () - * test avrà valore 0.

il comportamento successivo dipendeva dal tipo di test. Abbiamo casi diversi: il test ha un costruttore predefinito, il test ha generato un costruttore predefinito, il test contiene un membro POD, un membro non POD ...

Supponendo che Test sia una classe con un costruttore definito, non c'è differenza. Quest'ultima forma rende un po 'più chiaro che il costruttore di Test è in esecuzione, ma questo è tutto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top