Was ist der Unterschied zwischenUniform Initialisierung Syntax Unterschied
A a{ A() };
tun und
A a(A{});
die Most Vexing Parse zu vermeiden? Wann sollte ich einen bestimmten verwenden?
Was ist der Unterschied zwischenUniform Initialisierung Syntax Unterschied
A a{ A() };
tun und
A a(A{});
die Most Vexing Parse zu vermeiden? Wann sollte ich einen bestimmten verwenden?
Die beiden Syntaxen sind in den meisten Situationen gleichwertig, und welche man wählt, ist meistens eine Frage des Geschmacks. Wenn Sie in einheitliche Initialisierung sind, würde ich tun vorschlagen:
A a{ A{} };
Andernfalls allein Klammern verwendet werden können, eindeutig zu machen:
A a((A())); // This can't be parsed as a function declaration
Hinweis, dass es eine Situation (sehr unwahrscheinlich ist, muss ich sagen,) wo die zwei in Ihrer Frage gezeigten Formen nicht gleichwertig sind. Wenn Ihre Klasse A
einen Konstruktor hat, der eine initializer_list<A>
nimmt, wird dieser Konstruktor über den Copykonstruktor begünstigt werden, wenn die Klammern verwendet:
#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"
}
Die obige Differenz wird in diesem live example gezeigt.
Eigentlich druckt der erste * nicht "copy-ctor" für mich. Ich denke, seine Kopie Elision. –
@MemyselfandI: Huh, richtig, der Compiler ist die Kopie - aber konzeptionell wird der Kopierkonstruktor ausgewählt –
Funktioniert copy-elision nur, wenn Optimierungen aktiviert sind? –
In den meisten Fällen sind sie gleichwertig, aber A a{ A() };
einen std::initializer_list
Konstruktor bevorzugen, wenn eine vorhanden ist, während A a(A{});
eine Bewegung/Copykonstruktor bevorzugen.
Wenn das Konstrukt einen move/copy -Konstruktor aufruft, kann die Konstruktion des neuen Objekts weggelassen werden, aber das ist für einen std::initializer_list
Konstruktor nicht möglich.
Keine Syntax wird jemals als Funktionsdeklaration geparst, so dass beide die am meisten ärgerliche Analyse vermeiden.
#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 dieser besonderen Situation wäre die einfachste Option 'A a;', oder? Wenn ich das nicht falsch verstehe, macht die von Ihnen vorgeschlagene Syntax nur Sinn, wenn das Temporär, das Sie an den Konstruktor von 'A' übergeben wollen, von einem anderen Typ als' A' ist, richtig? I.e. 'A a {B()};'. – jogojapan