Wie ich weiß, std::allocator<T>::construct
werden in älteren Versionen von C ++ nur zwei Parameter verwendet. Der erste ist ein Zeiger auf einen unkonstruierten Rohspeicher, in dem ein Objekt vom Typ erstellt werden soll, T
und der zweite ist ein Wert vom Elementtyp, um dieses Objekt zu initialisieren. Also wird der Kopierkonstruktor aufgerufen:
struct Foo {
Foo(int, int) { cout << "Foo(int, int)" << endl; }
/*explicit*/ Foo(int) { cout << "Foo(int)" << endl; }
Foo(const Foo&) { cout << "Foo(const Foo&)" << endl; }
};
int main(int argc, char* argv[]) {
allocator<Foo> a;
Foo* const p = a.allocate(200, NULL); // second parameter is required on C++98 but on C++11 it is optional
// Foo* const p = a.allocate(200); // works fine on C++11 but not on C++98
a.construct(p, 5, 7); // works on C++ 11 and up but not C++98
a.construct(p, 10);// works on both
a.destroy(p);
a.destroy(p + 1);
a.deallocate(p, 200);
std::cout << std::endl;
}
Warum
a.construct(p, 10)
ruft unter C ++ 98 der Kopierkonstruktor auf, unter C ++ 11 und höher jedoch nur der Konstruktor, der eine Ganzzahl akzeptiert?Bedeutet dies , dass auf C ++ 11 wegen einer Copy-elision Optimierung auch wenn der Konstruktor
Foo(int)
sindexplicit
Werke auf diesem Aufruf:a.construct(p, 5)
Arbeiten auf C ++ 11 auch der Konstruktor ist ,explicit
was ich bin sicher, es ist nicht auf C nicht funktioniert ++ 98 , wennFoo(int)
istexplicit
.Wenn ja, wenn ich diese Anweisung mit einer Art Deaktivierungsoptimierung kompiliere,
copy-elision
führt dies dazu, dass der Compiler fehlschlägt? Vielen Dank.
Antworten:
Dies liegt daran, dass die Deklaration von
construct
in C ++ 11 geändert wurde :Die erste Deklaration ruft den Kopierkonstruktor auf, während die zweite Deklaration einen Konstruktor aufruft, der der angegebenen Liste von Argumenten entspricht. Dies kann der Kopierkonstruktor sein, aber auch ein anderer Konstruktor, wie Sie in Ihrem Code gesehen haben.
a.construct(p, 10)
Ruft den Kopierkonstruktor in C ++ 98 auf, da der10
implizitFoo
über denFoo(int)
Konstruktor konvertiert wird . Diese Konvertierung ist in C ++ 11 nicht erforderlich, da es einen passenden Konstruktor gibt, der ein verwendetint
(genau den Konstruktor, der für die Konvertierung in C ++ 98 verwendet wurde). Dies ist auch der Grund, warum der Code beim Hinzufügen in C ++ 98 nicht funktioniertexplicit
- er kann den Code nicht in10
einenFoo
Dann konvertieren .quelle