Inizializzazione dell'elenco con bretelle-init-list vuote (inizializzazione del valore o inizializzatore_list) rispetto all'inizializzazione predefinita esplicita, per i tipi di "lista"

3

Sfondo

In base all'articolo 4 di Scott Mayers C ++ efficace , se appropriato, può essere una buona pratica inizializzare tutte le proprietà dei membri dei tipi personalizzati tramite elenco di inizializzazione dei membri (nello stesso ordine delle loro dichiarazioni), anche per i tipi non POD con CTOR predefinito accessibile: s.

[Excerpt From: Scott Meyers. “Effective C++ Third Edition 55 Specific Ways to Improve Your Programs and Designs.”]

Item 4: Make sure that objects are initialized before they're used

...

For objects of built-in type ..., there is no difference in cost between initialization and assignment, but for consistency, it's often best to initialize everything via member initialization. Similarly, you can use the member initialization list even when you want to default-construct a data member; just specify nothing as an initialization argument.”

... but having a policy of always listing every data member on the initialization list avoids having to remember which data members may go uninitialized if they are omitted.

Ora, per le variabili membro che hanno tipi che hanno CTOR: s che accetta un parametro std::initializer_list e dove una "lista" ha un valore descrittivo stesso il tipo (ad esempio per std::vector ), anche per la costruzione predefinita potrebbe essere utile e descrittivo utilizzare un elenco di parentesi inserito vuoto nell'inizializzazione esplicita della variabile nell'elenco di inizializzazione dei membri del tipo proprietario.

Consideriamo ad es. un tipo personalizzato con un membro std::vector che deve essere inizializzato come vuoto. Per tali situazioni, ho visto le seguenti tre varianti (nel contesto dell'utilizzo esplicito dell'elenco di inizializzazione dei membri per il membro std::vector ):

// A) Using std::vector:s default CTOR.
struct FooA {
  FooA() : numbers() {};
private:
  std::vector<int> numbers;
};

// B) Using an empty braced-init-list invoking value-initialization;
//    also using std::vector:s default CTOR.
struct FooB {
  FooB() : numbers{} {};
private:
  std::vector<int> numbers;
};

// C) Empty braced-init-list used to explicitly invoke std::vector:s
//    std::initialization_list CTOR.
struct FooC {
  FooC() : numbers({}) {};
private:
  std::vector<int> numbers;
};

Dove il "valore descrittivo" dell'uso di una lista di parentesi chiusa vuota può essere evidente quando si confronta con il caso non vuoto:

// D) Non-empty braced-init-list use to explicitly invoke std::vector:s
//    std::initialization_list CTOR.
struct FooD {
  FooD() : numbers({1, 2, 3}) {};
  /* or: 
  FooD() : numbers{1, 2, 3} {}; */
private:
  std::vector<int> numbers;
};

Domande

  • [Q1] Quando confronti A & B vs C sopra: potrebbe quest'ultimo essere non preferito w.r.t. un po 'di overhead quando si chiama esplicitamente il std::initializer_list CTOR con una lista vuota? (Rispetto al semplice utilizzo diretto del CTOR predefinito).

  • [Q2] W.r.t. best practice / mostrare l'intento: si potrebbe preferire l'uso di una lista di parentesi (B & C) vuota su una chiamata CTOR predefinita esplicita (A) nei casi in cui una "lista" ha un valore descrittivo diretto al tipo che inizializza (ad es. std::vector )? O preferiamo piuttosto essere espliciti sulla chiamata al CTOR predefinito (A e possibile B), non mettendo troppo peso nella descrizione della "lista associazione" del tipo?

(Questo è il mio primo post su SE-Software Engineering, si spera che sia un po ' on-topic qui, come ho ritenuto inappropriato per StackOverflow (principalmente a causa della Q2 sopra), per favore mi consigli se diversamente)

    
posta dfri 01.07.2017 - 12:53
fonte

1 risposta

4

Stai effettivamente parlando della distinzione tra "inizializzazione del valore" ( T{} ) e "ecco un elenco di valori che sembra essere vuoto" ( T({}) ). Direi che le migliori pratiche dovrebbero essere fare la cosa che meglio descrive il tuo intento.

C'è una differenza tra il valore di inizializzazione di vector e l'inizializzazione di uno da una lista che è semplicemente vuota. In quest'ultimo caso, potresti un giorno aggiungere uno o più elementi a quella lista. Nel primo caso, non lo farai mai. Quindi devi fare ciò che meglio descrive il significato del tuo codice.

Per quanto riguarda la questione dell'efficienza, quasi certamente non ha importanza. Dovresti iniziare dal punto di vista della chiarezza del codice; se le prestazioni diventano un problema, puoi regolarle in un secondo momento. La scelta tra "lista vuota" e "inizializzazione del valore" riguarda innanzitutto la comunicazione del tuo intento.

    
risposta data 01.07.2017 - 16:38
fonte

Leggi altre domande sui tag