Domanda Differenza di sintassi di inizializzazione uniforme


Qual è la differenza tra fare

A a{ A() };

e,

A a( A{} );

per evitare il La maggior parte dei Vexing Parse? Quando dovrei usare un particolare?


10
2018-05-31 22:41


origine


risposte:


Le due sintassi sono equivalenti nella maggior parte delle situazioni e quale scegliere è principalmente una questione di gusti. Se si utilizza un'inizializzazione uniforme, suggerirei di fare:

A a{ A{} };

Altrimenti, le parentesi da sole possono essere usate per disambiguare:

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

Si noti che esiste una situazione (molto improbabile, devo dire) in cui le due forme mostrate nella domanda non sono equivalenti. Se la tua classe A ha un costruttore che accetta un initializer_list<A>, il costruttore verrà preferito al costruttore di copie quando vengono utilizzate le parentesi graffe:

#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 sopra è mostrata in questo esempio dal vivo.


13
2018-05-31 22:49



Nella maggior parte delle situazioni sono equivalenti, ma A a{ A() }; preferirà a std::initializer_list costruttore se uno è presente, mentre A a( A{} ); preferirà un costruttore di mosse / copie.

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

Né la sintassi sarà mai analizzata come una dichiarazione di funzione, quindi entrambi evitano l'analisi più irritante.

#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"
}

9
2018-05-31 22:50