Als ich die Antwort auf diese Frage las, war ich überrascht, das zu finden std::min(std::initializer_list<T>)
verwendet Argumente nach Wert.
Wenn Sie std::initializer_list
auf die Weise verwenden, die durch seinen Namen angedeutet wird, d. h. als Initialisierer für ein Objekt, verstehe ich, dass wir seine Elemente nicht kopieren wollen, da sie sowieso kopiert werden, um das Objekt zu initialisieren. In diesem Fall benötigen wir hier jedoch höchstwahrscheinlich keine Kopie, daher erscheint es viel sinnvoller, die Argumente als std::initializer_list<const T&>
zu verwenden, wenn dies nur möglich wäre.
Was ist die beste Vorgehensweise für diese Situation? Sollten Sie die initializer_list
Version von std::min
nicht aufrufen, wenn Sie nicht unnötige Kopien machen wollen, oder gibt es einen anderen Trick, um die Kopie zu vermeiden?
Es gibt keine std::initializer_list<const T&>
. Initialisierungslisten können nur Objekte nach Wert halten.
Siehe [dcl.init.list] / 5:
Ein Objekt vom Typ
std::initializer_list<E>
wird aus einer Initialisierungsliste erstellt, als ob die Implementierung ein temporäres Array von N Elementen vom Typconst E
zugewiesen hat, wobei N die Anzahl der Elemente in der Initialisierungsliste ist.
Es gibt keine Arrays von Referenzen, daher kann auch kein initializer_list
von Referenzen vorhanden sein.
Mein Vorschlag in diesem Fall wäre, einen Ersatz für std::min
zu schreiben, der eine variable Vorlage von Weiterleitungsreferenzen benötigt. Das funktioniert (obwohl ich mir sicher bin, dass es verbessert werden kann):
So funktioniert es - mit min
oder mmin
werden zwei zusätzliche Kopien erstellt (für a
und b
).
Um die Kommentare zusammenzufassen:
Ein std::initializer_list
soll ein Lightweight-Proxy sein, wie in cppreference.com beschrieben.
Daher sollte eine Kopie einer Initialisierungsliste sehr schnell sein, da die zugrunde liegenden Elemente nicht kopiert werden:
C ++ 11 §18.9 / 2
Ein Objekt vom Typ
initializer_list<E>
bietet Zugriff auf ein Array von Objekten vom Typconst E.
[ Hinweis: Ein Paar Zeiger oder ein Zeiger plus eine Länge wären offensichtlich Darstellungen fürinitializer_list
.initializer_list
wird verwendet, um Initialisierungslisten wie in 8.5.4 spezifiziert zu implementieren. Beim Kopieren einer Initialisierungsliste werden die zugrunde liegenden Elemente nicht kopiert. - Endnote ]
Die Verwendung einer Referenz würde jedoch auf die Verwendung eines Zeigers und damit auf eine zusätzliche Indirektion hinauslaufen.
Das eigentliche Problem von std::min
ist also nicht, dass es den Wert initializer_list
nach Wert nimmt, sondern dass die Argumente zu initializer_list
kopiert werden müssen, wenn sie zur Laufzeit berechnet werden. [1]
Dass die Benchmark bei [1] gebrochen wurde, wie sich herausstellte, später ist bedauerlich. p>
%Vor%
[1]: N2722 p. 2
Tags und Links c++ c++11 c++-standard-library std min