2013-05-31 14 views
10

Qual è la differenza tra fareinizializzazione Uniform differenza sintassi

A a{ A() }; 

e,

A a(A{}); 

per evitare il Most Vexing Parse? Quando dovrei usare un particolare?

+2

In questa situazione particolare, l'opzione più semplice sarebbe "A a;", giusto? Se non lo capisco male, la sintassi che suggerisci ha senso solo quando il temporaneo che vuoi passare al costruttore di 'A' è di tipo diverso da' A', corretto? Cioè 'A a {B()};'. – jogojapan

risposta

13

I due sintassi sono equivalenti nella maggior parte delle situazioni, e quale scegliere è in gran parte una questione di gusto. Se siete in inizializzazione uniforme, vorrei suggerire di fare:

A a{ A{} }; 

In caso contrario, le parentesi da solo può essere usato per disambiguare:

A a((A())); // This can't be parsed as a function declaration 

avviso, che c'è una situazione (molto improbabile, devo dire) dove le due forme mostrate nella domanda non sono equivalenti. Se la classe A ha un costruttore che prende un initializer_list<A>, che il costruttore sarà favorito il costruttore di copia quando si utilizzano le parentesi:

#include <initializer_list> 
#include <iostream> 

struct A 
{ 
    A() { } 
    A(std::initializer_list<A> l) { std::cout << "init-list" << std::endl; } 
    A(A const& a) { std::cout << "copy-ctor" << std::endl; } 
}; 

int main() 
{ 
    A a(A{}); // Prints "copy-ctor" (or nothing, if copy elision is performed) 
    A b{A()}; // Prints "init-list" 
} 

La differenza di cui sopra è mostrato in questa live example.

+2

In realtà, il primo * non * stampa "copy-ctor" per me. Penso che la sua copia-elisione. –

+0

@MemyselfandI: Huh, giusto, il compilatore sta eliminando la copia - ma concettualmente, il costruttore della copia è selezionato –

+0

La copia-elisione si verifica solo quando le ottimizzazioni sono abilitate? –

9

Nella maggior parte dei casi sono equivalenti, ma A a{ A() }; preferirà un costruttore std::initializer_list se uno è presente, mentre A a(A{}); preferirà un costruttore di spostamento/copia.

Quando il costrutto termina chiamando un costruttore di mosse/copie, la costruzione del nuovo oggetto può essere elidata, ma questo non è possibile per un costruttore std::initializer_list.

Né sintassi sarà mai analizzato come una dichiarazione di funzione, in modo da evitare sia il più-fastidioso-parse.

#include <iostream> 
#include <initializer_list> 
struct A { 
    A() { 
     std::cout << "A()\n"; 
    } 
    A(A&&) { 
     std::cout << "A(A&&)\n"; 
    } 
    A(std::initializer_list<A>) { 
     std::cout << "A(std::initializer_list<A>)\n"; 
    } 
}; 
int main() 
{ 
    {A a{ A() };} // Prints "A()\n" "A(std::initializer_list<A>)\n" 
    {A a(A{});} // Prints "A()\n" and *possibly* 
        // (depending on copy elision) "A(A&&)\n" 
} 
Problemi correlati