Verständnis "const" pointer
-
Hallo Zusammen,
ich habe ein Vreständnis Problem was "const" angeht:)
ich habe eine Factory, welche eine Methode :
Foo const* Factory::create() { Foo * p = new Foo (); _foos.append(p); return p; }
hier gebe ich einen konstanten Zeiger des Foo Objekt nach erzeugen nach "außen" , so dass der Ptr außen nicht mehr veränder werden darf, richtig?
Nun hat meine Foo Klasse eine Methode:
void Foo::DoSomething() { ... }
wenn ich dann folgendes machen will:
Foo const *p = create(); p->DoSomething(); //<-- geht nich weggen const ptr!?!?
Warum? Denk ich falsch? Ich möchte lediglich, dass der Pointer nicht verbogen wird
-
In deinem jetztigen Code ist
p
const, aber nicht der Zeiger, der aufp
zeigt.
Das sollte dann so aussehen:Foo const* Factory::create() { Foo * p = new Foo (); _foos.append(p); return p; } int main() { Foo const* const f = create(); // f und das Objekt, auf das f zeigt, sind const }
Wenn du eine non-const Methode auf
f
aufrufen möchtest, darf das Objekt, auf dasf
zeigt, nicht const sein.Foo* Factory::create() { Foo * p = new Foo (); _foos.append(p); return p; } int main() { Foo* const f = create(); // nur f ist const, das Objekt, auf das f zeigt, nicht }
Nachtrag:
Als Faustregel kannst du dir merken, dass alles, was links vom*
steht, sich auf das Objekt bezieht, auf das der Zeiger zeigt. Darum ist es auch egal, ob manconst Foo*
oderFoo const*
schreibt. Alles was rechts vom*
steht bezieht sich auf die Variable, die den Zeiger hält.
-
@DocShoe hmmm.. d.h. aber ich habe ja keinen zeiger der auf p zeigt, p ist der zeiger, welchen ich ich "create" zurückgeben will, und zwar so, dass diese außen nich verändert werden darf! ?
d.h. wenn ein Programmieret hier :
Foo* const f = create();
"const" weg lässt, dann kann er misst bauen!? aber ich hätte gern gehabt, dass schon die create Methode diese Restriktionen mit sich bringt!?
NACHTRAG: AHHH.. d.h. wenn ich
Foo*const Factory::create()
ist der ptr konstant nach außen
-
-
ja weil das erzeugt Objekt der Factory, an sich verändert werden darf, aber dessen Addresse nicht (deswegen konstanter Ptr)
Oder ist das Schwachsinn was ich mir da ausdenke?;)
-
@SoIntMan sagte in Verständnis "const" pointer:
ja weil das erzeugt Objekt der Factory, an sich verändert werden darf, aber dessen Addresse nicht (deswegen konstanter Ptr)
Oder ist das Schwachsinn was ich mir da ausdenke?;)
Ja
-
Wie sollte denn die Adresse in der Factory verändert werden?
-
@manni66
Ne die Factory, erzeugt eine Object Foo und gibt dessen ptr zurück, damit der Ptr des Objects außerhalb der Factory nich verändert werden kann. Aber wenn ich da falsch denke, dann lass ich das @DocShoe
-
@SoIntMan sagte in Verständnis "const" pointer:
@manni66
Ne die Factory, erzeugt eine Object Foo und gibt dessen ptr zurück, damit der Ptr des Objects außerhalb der Factory nich verändert werden kann.
int a = 42; int* b = &a; b = nullptr;
Wurde hier die Adresse von a geändert?
-
Du veränderst nicht die Adresse des Objektes, sondern den Inhalt der Zeigervariablen, die auf das Objekt zeigt. Das ist dem eigentlichen Objekt total schnuppe, das behält seine Adresse. Wenn du deinen Namen auf einen Zettel schreibst, später durchstreichst und durch einen neuen Namen ersetzt behältst du ja auch deinen Namen. Nur aufm Zettel steht halt was anderes.
-
@DocShoe und @manni66 AHHHH.. click.. ja ok , das war ein Griff ins Klo:) Jetzt raff ich das, vielen dank;)
-
Warum gibst du nicht einfach eine Referenz zurück und speicherst den Pointer.
-
@spiri sagte in Verständnis "const" pointer:
Warum gibst du nicht einfach eine Referenz zurück und speicherst den Pointer.
Weil das ganz ganz furchtbarer Stil wäre?
-
@hustbaer sagte in Verständnis "const" pointer:
@spiri sagte in Verständnis "const" pointer:
Warum gibst du nicht einfach eine Referenz zurück und speicherst den Pointer.
Weil das ganz ganz furchtbarer Stil wäre?
Weil man im C++ eine Referenz statt einem konstanten Pointer nimmt.
-
@spiri sagte in Verständnis "const" pointer:
Weil man im C++ eine Referenz statt einem konstanten Pointer nimmt.
Als Rückgabetyp? Nein, ganz sicher nicht. Und schon dreimal nicht bei Factory-Funktionen.
-
Doch als Rückgabetyp. Dann hast du einen konstanten Pointer den du nicht mehr umbiegen kannst. Und brauchst nicht mehr mit dem Dereferenzierungsoperator zu hantieren.
-
Das führt aber zu Problemen, wenn du
auto xy = getSomething();
schreibst. Und schwupps hast du eine Kopie. Const ref also nur in Zusammenhang mit fehlendem Kopierkonstruktor.Aber noch viel wichtiger: wie lange lebt denn so ein Objekt? Und wer gibt es frei?
delete &referenz;
ist Blödsinn.Die Factory sollte doch wohl besser einen
std::unique_ptr<Base>
zurückgeben?
-
@wob sagte in Verständnis "const" pointer:
Das führt aber zu Problemen, wenn du
auto xy = getSomething();
schreibst.Dann schreibt man halt
auto&
. Man soll wissen ob man eine Referenz oder eine Kopie will. Ich schreibe auch immerauto*
, weil man dann noch wenigstens erkennt, dass man einen Pointer bekommt.
-
Dieser Beitrag wurde gelöscht!
-
@spiri sagte in Verständnis "const" pointer:
Doch als Rückgabetyp.
Nein. Referenzen zurückzugeben ist grundsätzlich schon fragwürdig, und wo es doch (aus mehr oder weniger gutem Grund) gemacht wird, heisst es: die Referenz die du da bekommst verweist auf ein Objekt das hoffentlich lange genug leben wird für das was du damit vor hast, du musst es aber nicht wegräumen, da kümmert sich dann irgendwer anderer drum - irgendwann mal. (Wobei eben genau diese Unklarheit was die genaue Lebenszeit betrifft der Grund ist warum ich das Zurückgeben von Referenzen für fragwürdig halte.)
Du kannst jetzt anderer Meinung sein, aber das ist der de-Facto Standard was Funktionen die Referenzen zurückgeben angeht. Dass man es technisch betrachtet anders machen kann ist klar. Man macht es aber einfach nicht. Vielleicht solltest du mal das hier lesen: https://en.wikipedia.org/wiki/Principle_of_least_astonishment
Dann hast du einen konstanten Pointer den du nicht mehr umbiegen kannst.
Nein. Was "man hat" kommt drauf an was man mit dem Returnwert macht. Man kann immer noch schreiben
T* p = &(theCrazyFactoryFunction());
Und hätte dann das selbe "Problem" - wobei ich es halt nicht als Problem ansehe.
Umgekehrt kann man auch jederzeit
T* const p = theNotSoCrazyFactoryFunction();
schreiben.
Und brauchst nicht mehr mit dem Dereferenzierungsoperator zu hantieren.
Was ja wohl vollkommen wurscht ist.