2014-07-13 12 views
7

Il progetto di libro Effective C++11 di Scott Meyers afferma:Qual è la differenza tra `Object obj (args ...)` e `Object obj {args ...}`?

Distinguere() {} e per la creazione di oggetti

Qual è la differenza tra Object obj(args...) e Object obj{args...}? e perché Scott lo dice.

Aggiornamento:

La domanda How to use C++11 uniform initialization syntax? chiede come, e questa domanda chiede perché.

Update2:

ho trovato il seguente link è utile e completamente risponde a questa domanda:

https://softwareengineering.stackexchange.com/questions/133688/is-c11-uniform-initialization-a-replacement-for-the-old-style-syntax

+0

possibile duplicato di [Come usare C++ 11 sintassi di inizializzazione uniforme?] (Http://stackoverflow.com/questions/7612075/how-to-use-c11-uniform-initialization-syntax) –

+0

@MattMcNabb, quella domanda richiede HOW, questa domanda richiede PERCHÉ. – xmllmx

+5

Questa domanda non chiede "PERCHÉ", e l'altra domanda riguarda l'inizializzazione uniforme. –

risposta

5

Qual è la differenza tra Object obj(args...) e Object obj{args...}?

Il primo è diretta inizializzazione mentre la seconda è diretta -list-inizializzazione. Questo è menzionato in due diverse sezioni:

§8.5/16 [dcl.init]

L'inizializzazione che si verifica nelle forme

T x(a); 
T x{a}; 

nonché in new espressioni (5.3.4), static_cast espressioni (5.2.9), conversioni di tipo notazione funzionale (5.2.3) e inizializzatori di base e membro (12.6.2) è chiamato inizializzazione diretta.

e §8.5.4/1 [dcl.init.list]

List-inizializzazione è l'inizializzazione di un oggetto o di riferimento da un controventata-init-list. Tale inizializzatore è chiamato un elenco di inizializzazione e le clausole di inizializzatore separate da virgola dell'elenco sono denominate elementi dell'elenco di inizializzazione. Un elenco di inizializzazione potrebbe essere vuoto. L'inizializzazione dell'elenco può verificarsi in contesti di inizializzazione diretta o di inizializzazione della copia; l'inizializzazione dell'elenco in un contesto di inizializzazione diretta è denominata inizializzazione elenco diretto e l'inizializzazione dell'elenco in un contesto di inizializzazione della copia è denominata inizializzazione elenco di copia.


Ci sono alcune differenze tra i due:

  • Se il tipo in costruzione ha un costruttore che prende un argomento initializer_list, -list-inizializzazione diretta preferirà sempre che costruttore. Altri costruttori verranno considerati solo se il costruttore initializer_list non è valido. §13.3.1.7/1 [over.match.list]

  • diretto-list-inizializzazione non consente ambito conversioni all'interno dell'elenco di argomenti. §8.5.4/3 [dcl.init.list]

  • Se il tipo di essere inizializzato è un aggregato, -list-inizializzazione diretta eseguirà l'inizializzazione aggregata. §8.5.4/3 [dcl.init.list]

  • L'ordine di valutazione degli elementi di un controventata-init-list da sinistra a destra. §8.5.4/4 [dcl.init.list]

  • si può evitare il parsing più fastidioso utilizzando diretta-list-inizializzazione

 

struct foo{}; 
    struct bar 
    {  
    bar(foo const&) {} 
    }; 

    bar b1(foo()); // most vexing parse 
    bar b2(foo{}); // all 3 of the following construct objects of type bar 
    bar b3{foo()}; 
    bar b4{foo{}}; 
1

Qual è la differenza tra obj Object (args ...) e Object obj {args ...}? e perché Scott lo dice.

La differenza è che nel primo caso, l'ordine di valutazione degli argomenti è non in sequenza (cioè non specificato), ma in quest'ultimo caso, l'ordine è da sinistra a destra (cioè in cui appaiono).

Il testo che segue da $ 5.2.2/8 [expr.call] (n3690) si occupa di Object(args...) forma:

Le valutazioni dell'espressione Postfix e degli argomenti sono tutti non in sequenza uno rispetto un altro. Tutti gli effetti collaterali delle valutazioni degli argomenti sono sequenziati prima dell'inserimento della funzione (vedere 1.9).

E il testo da $ 8.5.4/4 [dcl.init.list] (n3690) si occupa di Object{args...} forma:

All'interno di inizializzazione-list di a-init-list rinforzato, il Le clausole di inizializzazione , comprese quelle risultanti dalle espansioni del pacchetto (14.5.3), sono valutate nell'ordine in cui appaiono. Vale a dire, ogni calcolo del valore ed e ff etto laterale associato a una data clausola inizializzatore viene sequenziato prima di ogni calcolo del valore ed ef fetto etto associato a qualsiasi clausola inizializzatore che lo segue in l'elenco separato da virgola dell'elenco inizializzatore. [Nota: questo ordinamento di valutazione è valido indipendentemente dalla semantica dell'inizializzazione ; ad esempio, si applica quando gli elementi dell'elenco inizializzatore vengono interpretati come argomenti di una chiamata del costruttore, anche se normalmente non vi sono vincoli di sequenziamento negli argomenti di una chiamata.- nota end]

Bene che significa che questo:

int f() { static int i = 10; return ++i; } //increment the static int! 

Object obj(f(), f()); //is it obj(11,12) or obj(12,11)? Unspecified. 

Object obj{f(), f()}; //it is obj(11,12). Guaranteed. 

noti che GCC (4.7.0 and 4.7.2) have a bug because of which {} form doesn't work the way it should. Non sono sicuro se è stato risolto nella versione corrente.

Spero che questo aiuti.

2

Il comportamento di Object obj(args...) e Object{args...} dipende dai costruttori definiti in Object.

Prendiamo il seguente esempio:

#include <iostream> 
#include <initializer_list> 

struct A 
{ 
    A(int a, int b) {std::cout << "Came to A::A()\n";} 
}; 

struct B 
{ 
    B(int a, int b) {std::cout << "Came to B::B(int, int)\n";} 
    B(std::initializer_list<int> in) {std::cout << "Came to B::B(std::initializer_list<int>)\n";} 
}; 

int main() 
{ 
    A a1(10, 20); // Resolves to A(int, int) 
    A a2{10, 20}; // Resolves to A(int, int) 
    A a3{30};  // Does not resolve to anything. It's a compiler error. 

    B b1(10, 20); // Resolves to B(int, int) 
    B b2{10, 20}; // Resolves to B(std::initializer_list<int>) 
    B b3{30};  // Resolves to B(std::initializer_list<int>) 

} 
1

Qual è la differenza tra Object obj (args ...) e Object obj {args ...}?

{args ...} preferirà un costruttore con una lista_inizializzazione rispetto ad altri candidati legali.

std::vector<int> v(10); // vector of size 10 
std::vector<int> v{10}; // vector initialized with a single element, (int) 10 

D'altra parte, si rinuncia al restringimento implicito.

std::vector<int> v(10.5); // vector of size 10 
std::vector<int> v{10.5}; // illegal - no compile 
std::vector<float> v{10.5}; // vector initialized with a single element, (float) 10.5 
Problemi correlati