Warum nimmt std :: min (std :: initializer_listT) Argumente nach Wert?

8

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?

    
gTcV 24.09.2014, 15:46
quelle

2 Antworten

5

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 Typ const 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):

%Vor%

So funktioniert es - mit min oder mmin werden zwei zusätzliche Kopien erstellt (für a und b ).

    
M.M 30.01.2015 22:40
quelle
2

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 Typ const E.   [ Hinweis:   Ein Paar Zeiger oder ein Zeiger plus eine Länge wären offensichtlich Darstellungen für initializer_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

    
mfuchs 30.01.2015 21:30
quelle