Jaka jest różnica między robiUniform inicjalizacji różnica składnia
A a{ A() };
, a
A a(A{});
uniknąć Most Vexing Parse? Kiedy powinienem użyć konkretnego?
Jaka jest różnica między robiUniform inicjalizacji różnica składnia
A a{ A() };
, a
A a(A{});
uniknąć Most Vexing Parse? Kiedy powinienem użyć konkretnego?
Dwie składnie są równoważne w większości sytuacji, a do wyboru należy przede wszystkim kwestia gustu. Jeśli jesteś w jednolitej inicjalizacji Sugerowałbym robi:
A a{ A{} };
Inaczej nawiasach sam może być używany do dwuznaczności:
A a((A())); // This can't be parsed as a function declaration
odnotować, że istnieje jedna sytuacja (bardzo mało prawdopodobne, muszę powiedzieć,), w przypadku gdy dwa formularze przedstawione w pytaniu nie są równoważne. Jeśli klasa A
ma konstruktora, że trwa initializer_list<A>
, że konstruktor będzie faworyzowany przez konstruktora kopii kiedy używane są szelki:
#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"
}
Powyższa różnica jest pokazana w tym live example.
Właściwie to pierwsze * nie * drukuje "kopia-ctor" dla mnie. Myślę, że jest to eliksir kopiowania. –
@MemyselfandI: Huh, prawda, kompilator usuwa kopię - ale konceptualnie konstruktor kopiowania jest wybierany –
Czy kopiowanie ma miejsce tylko wtedy, gdy włączone są optymalizacje? –
W większości przypadków są one równoważne, ale A a{ A() };
woli konstruktor std::initializer_list
, jeśli taki jest obecny, natomiast A a(A{});
woli konstruktor ruchu/kopiowania.
Po zakończeniu konstruowania wywołania konstruktora ruchu/kopiowania, konstrukcja nowego obiektu może zostać usunięta, ale nie jest to możliwe dla konstruktora std::initializer_list
.
Żadna składnia nigdy nie zostanie zanalizowana jako deklaracja funkcji, więc obie metody unikają najbardziej irytujących analiz.
#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"
}
W tej konkretnej sytuacji najprostszą opcją byłoby "A a;", prawda? Jeśli tego nie zrozumiem, sugerowana przez ciebie składnia ma sens tylko wtedy, gdy tymczasowy plik, który chcesz przekazać do konstruktora 'A' jest innego typu niż' A', prawda? To znaczy. 'A a {B()};'. – jogojapan