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?
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?
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.
In realtà, il primo * non * stampa "copy-ctor" per me. Penso che la sua copia-elisione. –
@MemyselfandI: Huh, giusto, il compilatore sta eliminando la copia - ma concettualmente, il costruttore della copia è selezionato –
La copia-elisione si verifica solo quando le ottimizzazioni sono abilitate? –
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"
}
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