vector :: clear in libc ++ für trivial zerstörbare Typen

8

Würde vector<T, std::allocator<T>>::clear() O(1) sein, wenn T trivial zerstörbar ist?

Die Implementierung von

gcc in bits/stl_vector.h ruft std::_Destroy ( bits/stl_construct.h ) auf. Diese Implementierung, die für den Fall optimiert wird, dass T durch Tag-Dispatching auf std::is_trivially_destructible<T> trivial zerstörbar ist.

Bei der Durchsicht der Implementierung von llvm (3.5.0) ruft vector::clear std::allocator<T>::destroy für jedes Element auf, das wiederum den Destruktor aufruft.

%Vor%

Würde dies am Ende optimiert werden, indem vector::clear() O(1) in libc ++ ebenfalls gemacht wird?

    
Pradhan 28.01.2015, 20:39
quelle

1 Antwort

4

Im Allgemeinen kann eine konforme Implementierung std::vector::clear in O (1) für Typen mit nicht-trivialen Destruktoren nicht implementieren.

C ++ 11 [container.anforderungen.general] / 3 Zustände:

  

Für die von dieser Subklausel betroffenen Komponenten, die einen allocator_type deklarieren, müssen in diesen Komponenten gespeicherte Objekte mit der Funktion allocator_traits<allocator_type>::construct erstellt und mit der Funktion allocator_traits<allocator_type>::destroy (20.6.8.2) zerstört werden.

Da clear size() Elemente zerstören muss, muss es unbedingt O (N) Aufrufe an die Funktion destroy des zugeordneten Zuordners machen. Das Endergebnis kann jedoch effektiv eine konstante Zeit benötigen, wenn jeder dieser Aufrufe null Zeit benötigt, um abgeschlossen zu werden (d. H. Nichts tut).

Ein kurzer Blick auf die Implementierung von _Destroy in Die aktuelle Revision von libstdc ++ 's bits / stl_construct.h zeigt, dass sie versucht, diese Optimierung nur dann auszuführen, wenn der Standardzuordner verwendet wird:

%Vor%

, aber leider nicht ganz richtig, da der Standard die Spezialisierung von Vorlagen im Namensraum std zulässt, die von benutzerdefinierten Typen abhängen ([namespace.std] / 1). Zum Beispiel, dieses Programm:

%Vor%

sollte ausgeben:

%Vor%

(die Reihenfolge der Elementzerstörung ist nicht spezifiziert, so dass die "zerstörenden" Zeilen in beliebiger Reihenfolge sein können, aber alle vorhanden sein müssen.) libstdc ++ "optimiert" fälschlicherweise die Aufrufe von allocator<mytype>::construct und allocator<mytype>::destroy , aber natürlich libc ++ macht es richtig ( DEMO ).

    
Casey 28.01.2015, 21:52
quelle

Tags und Links