Ich erstelle eine praktische display()
-Funktionsvorlage für Containertypen. Die Ausgabe für das letzte Element unterscheidet sich vom Rest, also überprüfe ich, ob myIterator != --cont.cend();
. Dies funktioniert für std::vector
, funktioniert aber nicht für std::array
. Warum?
Hier ist ein MWE (nicht mein tatsächlicher Code):
%Vor%Es hängt davon ab, wie der Iterator definiert ist.
Es scheint, dass der Iterator für die Klassenvorlage std::array
als Zeiger definiert ist. So fangen die Funktionen an, enden. cbegin, cend return nur den Zeiger. Wenn der Zeiger also als Wert zurückgegeben wird, darf er nicht verkleinert werden, weil lvalue
erforderlich ist.
Für die Klassenvorlage std::vector
ist der Iterator als eine benutzerdefinierte Klasse definiert, für die der Operator - () definiert ist.
Betrachten Sie das folgende Demonstrationsprogramm
%Vor%Berücksichtigen Sie, dass Sie
schreiben können %Vor%statt
%Vor% vorausgesetzt, Sie fügen header <iterator>
ein.
Sie können den Operator mit den umgekehrten Iteratoren der Klassenvorlage std::array
verwenden, da der Standard sie explizit wie
und die benutzerdefinierte Klasse std::reverse_iterator
definiert operator --()
.
Hier ist ein Demonstrationsprogramm
%Vor%Da dies Sprachanwalt , [expr.pre.increment] und [expr.post.increment] haben beide die Einschränkung, dass:
Der Operand soll ein veränderbarer Wert sein.
Nun sind weder vec.end()
noch arr.end()
lvalues, aber beide Typen sind implementierungsdefiniert (für Array und für Vektor ). In beiden Fällen würde ein einfacher Zeiger alle Iteratoranforderungen für diese Container erfüllen - und dies wäre ein Typ, der ein eingebautes Präfix und Postfix-Inkrement verwendet. In diesem Fall wäre --c.end()
aufgrund der genannten Einschränkung schlecht ausgebildet. Wenn der Iteratortyp jedoch ein -Klassentyp ist, gilt die obige Einschränkung nicht - da wir nicht die eingebauten Inkrementoperatoren verwenden - und das Aufrufen von operator--()
für eine Klasse hat diese Einschränkung nicht darauf (obwohl es könnte, wenn die Mitgliedsfunktion lvalue-reference-qualifiziert wäre).
So --c.end()
für entweder Vektor oder Array funktioniert nicht garantiert, da, wenn end()
einen Zeiger zurückgibt, dies nicht korrekt ist, und end()
darf einen Zeiger zurückgeben. In Ihrer speziellen Implementierung hat vector
's iterator
den Klassentyp, aber array
' s iterator
ist nur ein Zeigertyp, weshalb der erste funktioniert, der zweite aber nicht.
Lieber std::prev(c.end())
, was für beide Arten von Containern für alle Implementierungen funktioniert.
Reduziere niemals einen R-Wert, selbst wenn es kompiliert wird. Es ist für Leser des Codes nicht intuitiv.
Verwenden Sie stattdessen std::prev
.
Tags und Links c++ language-lawyer iterator stdarray