[] operator überladen
-
Hallo,
ich schreib mir grad einen kleinen wrapper und da bin ich auf ein problem gestoßen, denn ich will den [] operator überladen, doch irgendwie muss das programm wissen, ob der operator auf der linken oder der rechten seite steht, damit man sagen kann, was wann gemacht werden soll.
test[n] = i; oder i = test[n];ich hoffe jemand versteht mein problem
schöne grüße
gucky
-
Warum?
#include <iostream> using namespace std; struct X { int a; int& operator[]( int p ) { return a; } }; int main() { X x; x[0] = 42; int v = x[0]; cerr << v << "\n"; }Das geht, mal davon abgesehen, dass es vollkommen sinnfrei ist.
-
Gucky schrieb:
doch irgendwie muss das programm wissen, ob der operator auf der linken oder der rechten seite steht
Nein, muss es nicht. Dafür gibt es Referenzen oder Proxy-Objekte, die man zurückgeben kann.
-
Eigentlich recht simpel... man beachte die Kommentare!
class MyClass { private: int m_val[10]; public: // member operator int& operator[](const int& rhs) { // prüfen, ob neben das Array gegriffen wurde return m_val[rhs]; } // falls m_val private muss globaler Operator friend sein friend int& operator[](MyClass& lhs, const int& rhs); }; // globaler operator int& operator[](MyClass& lhs, const int& rhs) { // prüfen, ob neben das Array gegriffen wurde return lhs.m_val[rhs]; }
-
Akiko schrieb:
int& operator[](const int& rhs)Warum
const int&und nichtintals Parameter? Oder noch besserunsigned intund mit einem bezeichnenderen Namen als "rhs" (z.B. "index").Akiko schrieb:
// globaler operator int& operator[](MyClass& lhs, const int& rhs)operator[]kann nicht global sein.Zudem sollte man unter Umständen eine Const-Überladung bereitstellen:
int MyClass::operator[](unsigned int index) const;
-
Nexus schrieb:
Akiko schrieb:
int& operator[](const int& rhs)Warum
const int&und nichtintals Parameter? Oder noch besserunsigned intund mit einem bezeichnenderen Namen als "rhs" (z.B. "index").Akiko schrieb:
// globaler operator int& operator[](MyClass& lhs, const int& rhs)operator[]kann nicht global sein.Zudem sollte man unter Umständen eine Const-Überladung bereitstellen:
int MyClass::operator[](unsigned int index) const;Ist Gewohnheit, da ich auf System mit 8, 16, 32 und 64 Bit unterwegs bin und in der Regel ein int 32 Bit groß ist. Per Value wären das immer 32 Bit, die transferiert werden, da aber eine Refrenzen intern ein Zeiger ist, wäre der Zeiger auf einem 8 oder 16 Bit System etwas kleiner, oder platzsparender.
Korrekterweise wäre wohl (solange es keine 128 Bit Systeme gibt) ein uint64_t gewesen.Weil lhs und rhs das Ganze genau beschreibt, lhs = left hand side (lvalue) und rhs = right hand side (rvalue). Gerade bei Kontruktoren und Operatoren finde ich das unheimlich anschaulich.
Ja, den braucht man allerdings nur selten. Ich lege den const operator immer nur dann an, wenn der Compiler meckert.
Solange dead-code-Optimierungen nicht richtig funktionieren, ist das glaub ich der bessere Weg.
-
Akiko schrieb:
Ist Gewohnheit, da ich auf System mit 8, 16, 32 und 64 Bit unterwegs bin und in der Regel ein int 32 Bit groß ist. Per Value wären das immer 32 Bit, die transferiert werden, da aber eine Refrenzen intern ein Zeiger ist, wäre der Zeiger auf einem 8 oder 16 Bit System etwas kleiner, oder platzsparender.

Und dann hoffst du, dass eine Indirektion über einen Zeiger schneller ist, was?
Korrekterweise wäre wohl (solange es keine 128 Bit Systeme gibt) ein uint64_t gewesen.
korrekt ist immer size_t. Dafür ist der da.
-
Akiko schrieb:
Weil lhs und rhs das Ganze genau beschreibt, lhs = left hand side (lvalue) und rhs = right hand side (rvalue). Gerade bei Kontruktoren und Operatoren finde ich das unheimlich anschaulich.
Oh boy...
Den Index bei operator [] als "rechte Seite" zu bezeichnen halte ich für ziemlich daneben.
Mal ganz davon abgesehen dasslvalueundrvaluenichts mit links oder rechts zu tun haben.Ja, den braucht man allerdings nur selten. Ich lege den const operator immer nur dann an, wenn der Compiler meckert.
Solange dead-code-Optimierungen nicht richtig funktionieren, ist das glaub ich der bessere Weg.Lebst du in den 80ern?
-
hustbaer schrieb:
Den Index bei operator [] als "rechte Seite" zu bezeichnen halte ich für ziemlich daneben.
Mal ganz davon abgesehen dasslvalueundrvaluenichts mit links oder rechts zu tun haben.Hehe, ja, heute ist das etwas irritierend, liegt aber daran, dass sich über die Zeit die Bedeutung etwas geändert hat. Es ist aber nach wie vor eine Eselsbrücke.
Wikipedia schrieb:
In C, the term lvalue originally meant something that could be assigned to (coming from left-value, indicating it was on the left side of the assignment operator), but since 'const' was added to the language, this now is termed a 'modifiable lvalue'.
hustbaer schrieb:
Lebst du in den 80ern?
Es gibt noch mehr als x86... zum Beispiel Embedded Rechner. Oder wenn du es ganz schräg magst, s390 und s390x mit 31 oder 62 Bit. Microkontroller sind in der Regel 8 oder 16 Bit CPUs, haben aber 32 oder 64 Bit ALUs. Ein Paradebeispiel wäre der 68000 als 32 Bit CPU, aber Zugriffe erfolgen in 16 Bit.
otze schrieb:
Und dann hoffst du, dass eine Indirektion über einen Zeiger schneller ist, was?
Das Compilat mal als Assembler ausgeben und dann siehst du, dass eine Referenz und ein Zeiger im Maschinencode identisch sind.
otze schrieb:
korrekt ist immer size_t. Dafür ist der da.
Stimmt für Zeigergrößen, aber nicht für die größtmögliche Zahl. Es gebe ja noch uint128_t (verständlich, irgendwie muss man ja auch ein SSE Register voll bekommen). Und im nächsten Jahr wird es dank AVX auch uint256_t geben.
-
OK, jetzt wird's mir hier zu albern.
-
Akiko schrieb:
otze schrieb:
Und dann hoffst du, dass eine Indirektion über einen Zeiger schneller ist, was?
Das Compilat mal als Assembler ausgeben und dann siehst du, dass eine Referenz und ein Zeiger im Maschinencode identisch sind.
Ja, ich weiß. Und dann hoffst du, dass deine Indirektion über einen Zeiger schneller ist. Mensch, wenn du eine Referenz übergibst und danach darauf zugreifst, dann findet eine Kopie statt. Deine Version ist also fast immer langsammer, wiel zu deiner Kopie noch eine Indirektion kommt.
Stimmt für Zeigergrößen, aber nicht für die größtmögliche Zahl.
beim operator[] geht es um Speicherzugriffe. Und Offensichtlich braucht man keine größeren Zahlenwerte als im SPeicher referenziert werden können, weil man damit eh ins Nirvana schreibt. Und size_t ist der Typ der exakt groß genug ist um die maximal allokierbare Speichergröße aufzunehmen. Hätte man also in deinem Code irgendeinen Vorteil irgendwas größeres zu nehmen? Nein, weil dein Array nicht größer sein kann. Verständlich genug? Super!
