Ich habe an mehreren Stellen gelesen, dass std :: vector verlangt, dass das Vorlagenargument standardmäßig konstruierbar ist. Heute habe ich es gerade mit einer meiner Klassen versucht, die einen delete
d Standardkonstruktor hat, und zu meiner Überraschung scheint es gut zu funktionieren (mit dem Standardkonstruktor von std :: vector). Ist dieses portable Verhalten oder ist dies ein Implementierungsdetail von gcc's STL und sollte ich annehmen, dass der Vektor sein Template-Argument als Standard-Konstrukt verwenden kann?
Die Anforderung in C ++ 03 besteht darin, dass Typen, die in einem Container gespeichert werden, CopyConstructible
und Assignable
sind (siehe §23.1 Containeranforderungen). In C ++ 11 sind diese Anforderungen jedoch gelockert und neigen dazu, sich auf die Operationen anzuwenden, die an dem Container ausgeführt werden. So hat eine einfache Standardkonstruktion keine Anforderungen (siehe teble 96, §23.1 in C ++ 11 Standard).
Sobald Sie versuchen, einen Vektor zu kopieren oder Elemente darin einzufügen, werden Sie die Anforderungen CopyInsertable
, CopyAssignable
, EmplaceConstructible
, MoveInsertable
, MoveAssignable
etc. erfüllen
Es gibt zwei vector<T>
-Member, die in C ++ 11 ein Standard-Konstrukt T
benötigen:
Nichts anderes. Wenn Sie also diese Signaturen verwenden, müssen Sie einen Standardkonstruktortyp haben, sonst nicht.
std::vector
erfordert nicht unbedingt, dass sein Elementtyp standardmäßig dekonstruierbar ist.
Die ursprüngliche Spezifikation von std::vector
(C ++ 98, C ++ 03) versucht niemals, ihre Elemente intern zu default-konstruieren. Alle neuen Elemente werden immer kopie-konstruiert von einem Objekt "von außen" (durch den aufrufenden Code) als Argument geliefert. Dies bedeutet, dass jedes Mal, wenn Sie default-konstruierte Elemente in Ihrem Vektor benötigen, es Ihre Seite des Codes (der Aufrufer) ist, die es standardmäßig konstruieren und an std::vector
als " Original "zu kopierendes Element.
Zum Beispiel, wenn Sie so etwas in C ++ 98 machen
%Vor%es erweitert sich tatsächlich in
%Vor%durch den Standardargumentmechanismus. Mit anderen Worten, das default-konstruierte "originale" Element wird dem Konstruktor des Vektors durch den aufrufenden Code geliefert, der nicht intern vom Vektor erzeugt wird.
C ++ 11 hat das geändert und jetzt hat std::vector
Methoden, die die Standard-Konstruktion seiner Elemente intern ausführen. Dies erfordert immer noch nicht unbedingt, dass Vektorelemente standardmäßig konstruierbar sind. Es bedeutet nur, dass Sie default-constructible-Elemente benötigen, um die spezifischen Methoden von std::vector
zu verwenden.
Nun, Vorlagen sind in gewisser Weise schwach typisiert. Das heißt, der fehlende Standardkonstruktor wird erst erkannt, wenn der Code die Methode, in der er verwendet wird, möglicherweise intern aufruft. Dies führt zu einem Kompilierungsfehler.
Wenn Sie jedoch nicht die Methoden verwenden, die intern den Standardkonstruktor verwenden, sind Sie "sicher". Ich weiß jedoch nicht, welches die "sichere" Teilmenge ist, und ich vermute, dass es nicht durch den Standard definiert ist. Beispiel: Vektorkopieren könnte resize
verwenden, was wiederum den Standardkonstruktor verwenden könnte.