Dieses Programm unbestimmtes Verhalten hat: der Compiler nicht i[0]
und i[2]
in einem von links nach rechts, um erforderlich ist, um zu bewerten (die Sprache C++ gibt diese Freiheit zu Compiler, um Optimierungen zu ermöglichen).
Zum Beispiel Clang does it in this instance, während GCC does not.
Die Reihenfolge der Auswertung ist nicht festgelegt. Sie können also keine konsistente Ausgabe erwarten, selbst wenn Sie Ihr Programm wiederholt auf einer bestimmten Maschine ausführen.
Wenn Sie konsistente Ausgabe erhalten möchten, können Sie die oben umformulieren wie folgt (oder in äquivalenter Weise):
cout << i[0];
cout << i[2];
Wie Sie sehen können, GCC no longer outputs 44
in diesem Fall.
EDIT:
Wenn aus welchem Grund auch immer, die Sie wirklich wirklich den Ausdruck einfügen möchten cout << i[0] << i[2]
24
drucken, erhalten Sie die Definition der überladenen Operatoren (operator []
und operator <<
) erheblich ändern müssen, denn die Sprache absichtlich macht es unmöglich zu sagen, welcher Teilausdruck (i[0]
oder [i2]
) zuerst ausgewertet wird.
Die einzige Garantie, die Sie hier bekommen, ist, dass das Ergebnis i[0]
der Auswertung in cout
, bevor das Ergebnis eingefügt werden soll i[2]
auszuwerten, um so die beste Wahl wahrscheinlich ist operator <<
führen die Modifikation von Int's
Daten Mitglied v
, lassen eher als operator []
.
jedoch das Delta, den v
angewandt werden soll, wird als Argument an operator []
vergangen, und Sie brauchen einen Weg, es zu operator <<
zusammen mit dem ursprünglichen Int
Objekt weitergeleitet werden.Eine Möglichkeit ist operator []
Rückkehr eine Datenstruktur zu lassen, der das Delta sowie ein Verweis auf das ursprüngliche Objekt enthält:
class Int;
struct Decorator {
Decorator(Int& i, int v) : i{i}, v{v} { }
Int& i;
int v;
};
class Int {
public:
int v;
Int(int a) { v = a; }
Decorator operator[](int x) {
return {*this, x}; // This is C++11, equivalent to Decorator(*this, x)
}
};
Jetzt brauchen Sie nur operator <<
so zu umschreiben, dass es akzeptiert eine Decorator
Objekt, ändert das referenzierte Int
Objekt durch das gespeicherte delta zum v
Datenelement Anlegen druckt dann seinen Wert:
ostream &operator<< (ostream &o, Decorator const& d) {
d.i.v += d.v;
o << d.i.v;
return o;
}
Hier ist ein live example.
Haftungsausschluss: Wie andere erwähnt haben, bedenken Sie, dass operator []
und operator <<
sind in der Regel nicht mutiert Operationen (genauer gesagt, sie nicht mutieren, den Zustand des Objekts, die indiziert ist und Strom eingefügt, respectively), Sie werden also davon abgehalten, Code wie diesen zu schreiben, es sei denn, Sie versuchen nur, einige C++ - Quizfragen zu lösen.
'cout << i [0] << i [2];' könnte auch so geschrieben werden: 'operator << (operator << (cout, i [0]), i [2]);' – Xaqq
scheint die Reihenfolge der Auswertung von zwei << nicht gut definiert. Debuggen Sie Ihren Code und Sie werden sehen, dass das i [2] zuerst aufgerufen wird. – Tim3880
Ich würde wirklich vorschlagen, dass 'operator []' Nebenwirkungen haben. Ich denke, dieses Verhalten wird dich irgendwann wieder beißen und nicht nur hier. Stellen Sie sich vor, wie das mit Multithreading interagiert, z.B. –