Welche legitimen Gründe gibt es, um den unären Operator & zu überlasten?

Antworten:

53

Ich erinnere mich an so etwas wie eine Smart-Pointer-Klasse, die überschrieben wurde, operator&weil sie die Adresse des enthaltenen Zeigers und nicht die Adresse des Smart-Pointer-Objekts zurückgeben wollte. Ich kann mich nicht erinnern, wo ich es gesehen habe oder ob es damals eine gute Idee war.

Aha, erinnert sich: Microsoft CComPtr .

Edit: Zur Verallgemeinerung, es könnte Sinn unter den folgenden Bedingungen:

  • Sie haben ein Objekt, das sich als ein anderes Objekt tarnt.
  • Dieses Objekt kann einen Zeiger auf das Objekt erhalten, als das es sich tarnt.

Die Rückgabe eines anderen als eines legitimen Zeigers würde gegen das Prinzip des geringsten Erstaunens verstoßen .

Mark Ransom
quelle
1
@ Billy, es ist sehr lange her, dass ich das benutzt habe und ich erinnere mich einfach nicht an die Vor- / Nachteile. Da das Übergeben der Adresse eines Schnittstellenzeigers in der COM-Programmierung häufig vorkommt, erscheint dies vertretbar.
Mark Ransom
" Adresse des enthaltenen Zeigers " Sie meinen den enthaltenen Zeiger, nicht wahr?
Neugieriger
5
@curiousguy Ich glaube nicht. Der enthaltene Zeiger hat den Typ T *. Der von zurückgegebene Zeiger operator&hat den Typ T **und zeigt auf den enthaltenen Zeiger.
2
Der Operator & Overload in CComPtr ist ein gefährlicher Hack. Dies funktioniert nur, wenn der Smart Pointer noch nicht initialisiert ist. Andernfalls wird die Referenzanzahl des Objekts, das es bereits enthält, nicht dekrementiert, und es gibt zahlreiche Lecks. In Debug-Builds wird tatsächlich behauptet, dass der Zeiger bereits null ist, da diese Art von Fehler viel zu häufig war.
Adrian McCarthy
11

Dies ist nützlich, wenn die &Operation in Lambda-Platzhalternotation dargestellt wird, z &_1[_2].

user541686
quelle
10

Wenn Sie unary &überladen , verhält sich Ihr Objekt (in dieser Hinsicht) wie eine Referenz .

Ich bin mir ziemlich sicher, dass es ein Kinderspiel ist, Alternativen zu integrierten Referenzen bereitzustellen, insbesondere da Referenzen in C ++ überhaupt keine Objekte sind und keine eigenen Adressen haben. Instanzen Ihres benutzerdefinierten Typs sind unweigerlich Objekte und haben Adressen, selbst wenn Sie die normale Methode zum Abrufen dieser Adresse deaktivieren. Es ist also niemals eine perfekte Nachahmung.

Aber die Leute sind sehr an benutzerdefinierten Alternativen zu Zeigern interessiert, sodass ich sehen kann, wie jemand es versuchen möchte. Ich bin nicht sicher, ob sie es vermeiden werden, einen Typ zu erstellen, der sich (falsch) so verhält, dass seine Benutzer wünschen, sie hätten sich nicht darum gekümmert.

Steve Jessop
quelle
Aber isocpp.org/wiki/faq/references#overview-refs sagt , dass: "Obwohl eine Referenz oft eine Adresse in der zugrunde liegenden Assemblersprache implementiert ist, denken Sie bitte nicht von einer Referenz als lustig aussehenden Zeiger auf ein Objekt. Eine Referenz ist das Objekt. Es ist weder ein Zeiger auf das Objekt noch eine Kopie des Objekts. Es ist das Objekt. "
Destruktor
1
@PravasiMeet: Es ist bedauerlich, dass sie es so ausdrücken, da der Standard ausdrücklich sagt, dass eine Referenz kein Objekt ist. Es ist wie der Name einer Variablen: Die Variable ist ein Objekt, der Name jedoch nicht. Die Referenz einer Referenz ist ein Objekt, die Referenz selbst jedoch nicht.
Steve Jessop
Können Sie bitte das Standardzitat angeben, das ausdrücklich besagt, dass eine Referenz kein Objekt ist?
Zerstörer
1
@PravasiMeet: hmm, ich dachte, es gibt eine klare Aussage, aber im Moment kann ich sie nicht finden, also ist sie vielleicht doch nicht explizit. [Intro.object] sagt jedoch "Ein Objekt ist ein Speicherbereich", und [dcl.ref] sagt in einer Notiz "Eine Referenz kann als Name eines Objekts betrachtet werden" und normativ "Es ist nicht spezifiziert, ob oder Keine Referenz erfordert Speicherung ".
Steve Jessop
Beachten Sie auch in den FAQ, dass zuerst "Was ist eine Referenz? Ein Alias ​​(ein alternativer Name) für ein Objekt" steht. Wenn sie also sagen, dass eine Referenz ein Name ist und eine Referenz das Objekt, dann sind sie konsistent, solange sie sagen würden, dass ein Name das Objekt ist. Für den Jargon des C ++ - Standards ist der Name eines Objekts jedoch auch kein Objekt. Es stellt das Objekt in Ausdrücken dar, das ist nicht dasselbe wie mit dem Objekt identisch zu sein , aber auf Englisch kann "ist" beides bedeuten.
Steve Jessop
8

Ich habe dies im Kontext eines DSL, das LLVM-Code generiert, erfolgreich durchgeführt. Ein Beispiel wird veranschaulichen. Sagen Sie xund ysind Werte (dh Objekte vom Typ value). Dann gibt der Ausdruck x+yeine ADD-Anweisung in einen Codestream aus. Sehr vernünftig gibt der Ausdruck &xeine Anweisung aus, die Adresse von zu übernehmen x.

AndyJost
quelle
8

Vier Jahre später eine andere Antwort.

Eine andere Verwendung, die ich gesehen habe, ist, wenn Sie die C ++ - Sprache huckepack nehmen, aber Ihre eigene Semantik definieren. Paradebeispiel: Boost.Spirit.

Boost.Spirit, insbesondere Qi zum Parsen, überlädt Operatoren auf Parsern, um eine EBNF-ähnliche Syntax zum Angeben beliebiger Parserobjekte bereitzustellen. Insbesondere ist der unäre &Operator überlastet, um den And-Predicate-Parser bereitzustellen .

And-Predicate Parser (& a)

Beschreibung

Syntaktische Prädikate bestätigen, dass eine bestimmte bedingte Syntax erfüllt sein muss, bevor eine andere Produktion bewertet wird. Ähnlich wie semantische Prädikate, eps, verbrauchen syntaktische Prädikate keine Eingabe. Das and-Prädikat & a ist ein positives syntaktisches Prädikat, das nur dann eine Übereinstimmung mit der Länge Null zurückgibt, wenn sein Prädikat übereinstimmt.

Anwendungsbeispiel:

Grundlegendes Beispiel für die Vorausschau: Stellen Sie sicher, dass das letzte Zeichen ein Semikolon ist, aber verbrauchen Sie es nicht. Schauen Sie sich nur das nächste Zeichen an:

test_phrase_parser("Hello ;", lit("Hello") >> &lit(';'), false);

Kurz gesagt, das Unäre hat &hier überhaupt keine Beziehung zu Zeigern; Es verfügt über eine domänenspezifische Semantik, die für Qi-Parser-Objekte gilt.

Anthony
quelle
2
Kurz gesagt, es ist die gleiche Antwort mit einem anderen Beispiel einer Ausdrucksvorlage
sehe
0

Früher habe ich den Operator & (ohne sein Verhalten zu ändern) als privat für die Klasse überschrieben, um mich vor der gelegentlichen Erstellung eines intelligenten Zeigers auf das im Stapel erstellte Objekt zu schützen. Ich bin mir immer noch nicht sicher, ob es wirklich eine gute Idee war ...

Andrey Betenev
quelle
2
Das ist eine schlechte Idee, weil Sie Ihr Ziel nicht erreicht haben. Siehe: stackoverflow.com/questions/6494591/…
Billy ONeal
-3

Sie können den Adressoperator überladen, um ihn privat zu machen. Dies kann nützlich sein, um eine Art Staffelübergabeschema zu implementieren, bei dem die Adresse des Staffelstabs nicht übernommen werden kann. Wenn die Konstrukteure des Schlagstocks versteckt sind, kann dies das Zielfernrohr des Schlagstocks luftdicht halten.

Thomas Eding
quelle
6
Sofern dies nicht std::addressofvorhanden ist, kann die Adresse weiterhin übernommen werden. stackoverflow.com/questions/6494591/…
Billy ONeal