Alle Arten von Klassen in der C++ - Standardbibliothek haben eine Member-Swap-Funktion, einschließlich einiger polymorpher Klassen wie std::basic_ios<CharT>
. Die Vorlagenklasse std::shared_future<T>
ist eindeutig ein Werttyp, und std::future<T>
ist ein Nur-Wert-Werttyp. Gibt es einen bestimmten Grund, sie bieten keine swap()
Member-Funktion?Warum std :: future <T> und std :: shared_future <T> nicht Mitglied swap() bieten?
Antwort
Member-Tausch war eine massive Leistungssteigerung vor std::move
Unterstützung in C++ 11. So konnten Sie beispielsweise einen Vektor an einen anderen Ort verschieben. Es wurde in vector
Größen ebenso verwendet, und es bedeutete, dass das Einfügen in einen Vektor von Vektoren war nicht vollständige Leistung Selbstmord.
Nach std::move
angekommen C++ 11, mit vielen manchmal leeren Typen die Standardimplementierung von std::swap
in:
template<class T>
void swap(T& lhs, T& rhs) {
auto tmp = std::move(rhs);
rhs = std::move(lhs);
lhs = std::move(tmp);
}
wird grundsätzlich so schnell wie ein custom-written sein.
Bestehende Typen mit swap
Mitgliedern sind unwahrscheinlich, sie (zumindest sofort) zu verlieren. Das Erweitern der API eines neuen Typs sollte jedoch gerechtfertigt sein.
Wenn std::future
im Grunde ein Wrapper um ein std::unique_ptr<future_impl>
ist, dann wird das obige 4 Zeiger Lesevorgänge, 3 Zeiger Schreibvorgänge und einen Zweig erfordern. Und ein optimierender Compiler, der ihn in die Zeile einfügte, konnte ihn auf 2 Zeigerlesevorgänge und 2 Zeigerschreibvorgänge reduzieren (unter Verwendung von SSA zum Beispiel), was eine optimierte .swap
Elementfunktion tun könnte.
So weiß es Zwischen Zugang zum lhs
und rhs
nie auftritt, also die Existenz von tmp
kann als-ob beseitigt werden, sobald es beweist tmp
ist leer und hat daher eine no-op dtor.
Static single assignment, wobei Sie ein Programm so abbrechen, dass jede Zuweisung zu einem Primitiv eine brandneue Variable (mit Metadaten) erstellt. Sie beweisen dann Eigenschaften über diese Variable und eliminieren redundante.
- 1. Std :: Future oder Std :: shared_future auf mehrere Threads warten
- 2. Wie benutze ich CMake Generator Ausdruck $ <TARGET_FILE: tgt>?
- 3. C++ was sind std :: shared_future und std :: promise
- 4. CAS: Entschlüsselung von TGT
- 5. Warum löscht std :: map < std::map > Speicher nicht?
- 6. setBase (8) und std :: cout << std :: Oktober
- 7. Warum std :: cout << haupt << std :: endl druckt 1?
- 8. Bedingte Std :: Future und Std :: Async
- 9. Warum std :: shared_ptr <T> = std :: unique_ptr <T[]> Kompilierung, während std :: shared_ptr <T[]> = std :: unique_ptr <T[]> nicht?
- 10. Wie std :: vector <std :: reference_wrapper <T>> konvertieren std :: vector <T>
- 11. Was macht std :: cout << std :: cin?
- 12. Std :: shared_future auf Raspberry Pi Toolchain
- 13. Warum "std :: vector <std::string> &" statt "void"?
- 14. Warum gibt es keinen Operator << für std :: unique_ptr?
- 15. Unterstützt std :: future Polymorphismus?
- 16. Warum in "std :: ostream & operator <<" Ich habe Speicherlecks?
- 17. Warum std :: future template Argumenttyp ist Referenztyp?
- 18. Unterschied zwischen std :: is_signed <T> und std :: numeric_limits <T> :: is_signed?
- 19. Keine bekannte Konvertierung für Argument 1 aus 'Std :: Vektor <Std :: Basic_string <char>> *' zu 'Const Std :: Vektor <Std :: Basic_string <char>> &'
- 20. Warum ist std :: min_element und Unternehmen nicht für std :: vector spezialisiert <bool>
- 21. Initialisierung von std :: pair <doppelt, std :: array <std :: pair <doppelt, doppelt>, 3>>
- 22. Die überladene Operator << Vorlage funktioniert nicht für std :: list, obwohl es für std :: vector
- 23. Std :: Ofstream akzeptiert nicht Const Char * für << Operator
- 24. OpenGL crash nur durch Entfernen von std :: cout << "hi" << std :: endl aus dem Programm
- 25. Iterieren über Std :: Map <X, Std :: Vektor <Y>> und Sortieren der Vektoren
- 26. Warum ist std :: rc :: Rc <> nicht kopieren?
- 27. Warum std :: map überladener Operator <nicht die
- 28. std :: lock_guard <pthread_mutex_t> kompiliert nicht
- 29. Warum ist std :: array < T, 0 > nicht leer?
- 30. emplace_back arbeitet nicht mit std :: vector <std :: map <int, int>>
Warum funktioniert eine Mitgliedsfunktion und nicht ein Freund für unqualifiziertes 'swap'? - Ich habe den Eindruck, dass gcc (4.8) bei der Optimierung von 'unique_ptr' schlecht ist. Obwohl es SSE verwendet, führt es viele unnötige Operationen durch. Vielleicht wegen der Ausnahmebehandlung, aber vielleicht auch, weil libstdC++ ''unique_ptr' ein' tuple' verwendet, um das komprimierte Paar aus Delet und Pointer zu implementieren, und Tupel könnte ziemlich schwer zu optimieren sein. – dyp
@dyp Klingt nach einem Grund, Ihren Optimierer besser zu machen, anstatt die Sprache zu ändern. Oder finde einen Weg, das komprimierte Tupel-Idiom als ein schwer zu optimierendes bibliotheksbasiertes 'Tupel' auszudrücken; wenn komprimiertes 'tuple' schwer zu optimieren ist, vielleicht ein' std :: tuple'? Das geht wahrscheinlich zu weit; dann ein eingebauter primitiver Produkttyp, der die Implementierung von komprimiertem 'std :: tuple 'vereinfacht? – Yakk
libC++ hat einen dedizierten 'compressed_pair' Typ, ich denke das hilft schon. Zumindest mit Kompilierzeiten. Ich habe mich über die Performance gewundert, da Howard Hinnant aus Performancegründen die Copy/Move + Swap-Sprache nicht mag. – dyp