Funktions Zeiger
-
Hallo wofür kann eine Funktion einen Zeiger zurückgeben?
Das würde doch eigentlich nur bei static Variablen Sinn machen oder?#include <iostream> #include <windows> using namespace std; int *f ( ) { int a = 3; return &a; // Fehler: a ist beim verlassen der Funktion nicht mehr gültig } int main() { int *b; b = f(); cout<<"Ausgabe: "<< *b << endl; system("PAUSE"); return 0; }
-
Eigentlich immer, außer bei lokalen Variablen.
-
Du kannst in der Funktion Objekte auf dem Heap erzeugen. Auch, wenn es nicht sonderlich schön und sicher ist:
myObject* CreateObject() { myObject* result = new myObject(); // mache diverse Dinge mit myObject return result; }Du musst das Objekt, auf das der Zeiger zeigt, aber gar nicht selbst erzeugen. Du könntest bspw. eine Suchfunktion erstellen, deren Ergebnis auf das gewünschte Element zeigt (ja, auch das ginge eleganter).
Oder du gewährst über Zeiger Zugriff auf Member eines Objektes (jaja, das ist auch kein toller Stil):
Auto meinAuto("Mercedes SLK"); Kofferraum* meinKofferraum = meinAuto.GetKofferraum(); meinKofferraum->oeffne();
-
Das machst du dann, wenn ein Objekt bereits vor dem Aufruf der Funktion existiert.
-
Gugelmoser schrieb:
Das machst du dann, wenn ein Objekt bereits vor dem Aufruf der Funktion existiert.
Weil:
static -> Referenz
Objekt wird erzeugt* -> Smartpointer
Getter, Suchfunktionen o.ä. -> Pointer.* Bei einer factory nimmt man vielleicht auch rohe Pointer, aber das würde ich mal als regelbestätigende Ausnahme sehen.

-
Also kann ich mir merken:
Lokale Variable in einer Funktion (Zeiger zurückgeben ist schlecht)
Lokale Statische Variable in einer Funktion (Zeiger zurückgeben ist okay)
Global Variable (Funktion darf ruhig einen Zeiger zurückgeben)#include <iostream> #include <windows> using namespace std; int glob; int *f ( ) { glob = 8; return &glob; // Ok glob ist Global } int *f_1 ( ) { int v; return &v; // Schlecht v ist beim austritt aus der Funktion nicht mehr gültig } int *f_2( ) { static v; return &v; // Ok wegen statischer Variable } int main() { int *b; int *c; int *d; b = f(); c = f_1(); d = f_2(); cout<<"Ausgabe: "<< *b << endl; cout<<"Ausgabe: "<< *c << endl; // Gibt bei mir jetzt auch Müll aus ^^ cout<<"Ausgabe: "<< *d << endl; system("PAUSE"); return 0; }
-
CppZgr schrieb:
Lokale Statische Variable in einer Funktion (Zeiger zurückgeben ist okay)
Global Variable (Funktion darf ruhig einen Zeiger zurückgeben)Nur dass da Referenzen üblicherweise mehr Sinn machen.
-
Frage mich übrigens warum überhaupt in dem Fall einen Pointer zurückgeben, warum nicht einfach der Funktion einen Pointer geben un den in der Funktion mit anderen Werten befüllen?
#include <iostream> using namespace std; void changevariable(char*); void changevariable(char* ptr) { *ptr = 'b'; // wir schreiben in die speicherzelle mit der adresse des pointers einen anderen buchstaben in diesem falle b } int main(int argc, char* argv[]) { char variable = 'a'; // wir schreiben den buchstaben a in die variable char* pointer = &variable; // wir schreiben die adresse der variable in den pointer changevariable(pointer); // wir übergeben den pointer (adresse) an die funktion cout << variable; // unsere ausgabe ergibt nun b weil wir den inhalt an der speicheradresse geändert haben system("pause"); return 0; }
-
cooky451 schrieb:
Getter, Suchfunktionen o.ä. -> Pointer.
Du gibst einen Zeiger auf das Attribut bei Getter zurück? Oder wie meinst du das?
CppZgr schrieb:
Lokale Variable in einer Funktion (Zeiger zurückgeben ist schlecht)
Ja, das ist ganz schlecht, weil die Variable am Ende der Funktion zerstört wird.
CppZgr schrieb:
Global Variable (Funktion darf ruhig einen Zeiger zurückgeben)
Das macht keinen Sinn, immerhin ist sie global. Da kann eh immer jeder drauf zugreifen.
-
@Gugelmoser das dass kein Sinn macht ist mir klar. Aber es ging mir halt um den Stern nachdem Datentyp.
Aber nochmal kurz
cooky451 schrieb:
Nur dass da Referenzen üblicherweise mehr Sinn machen.
Meintest du das so mit der Referenz?
Weil da ist doch jetzt kein unterschied beide Funktionen sind intern gleich.#include <iostream> #include <windows> using namespace std; int glob; int glob_2; int &f ( ) // Mit Referenz { glob = 8; return glob; } int *f_2 ( ) // Mit Zeiger { glob_2 = 1; return &glob_2; } int main() { int b; int *c; b = f(); c = f_2(); cout<<"Ausgabe: "<< b << endl; cout<<"Ausgabe: "<< *c << endl; system("PAUSE"); return 0; }
-
#include <iostream> using namespace std; void f (int* ptr) { *ptr=8; } int main() { int b; int* c; f(&b); // mit referenz f(c); // mit zeiger cout<<"Ausgabe: "<< b << endl; cout<<"Ausgabe: "<< *c << endl; system("PAUSE"); return 0; }
-
Gugelmoser schrieb:
cooky451 schrieb:
Getter, Suchfunktionen o.ä. -> Pointer.
Du gibst einen Zeiger auf das Attribut bei Getter zurück? Oder wie meinst du das?
Wenn das Attribut optional ist und keinen "Nullzustand" hat, natürlich. Wie auch sonst?

CppZgr schrieb:
Meintest du das so mit der Referenz?
Weil da ist doch jetzt kein unterschied beide Funktionen sind intern gleich.Ein Pointer würde Sinn machen, wenn man noch nicht genau wüsste ob das Objekt auch existiert. Aber bei globalen oder statischen Variablen kann man sich ziemlich sicher sein, dass die da sind. Daher Referenzen.
-
@Videonauth: GCC unter Linux
Compile:22:15: Fehler: »system« wurde in diesem Gültigkeitsbereich nicht definiert [Habe ich rausgemacht 6:5: Warnung: »c« wird in dieser Funktion uninitialisiert verwendet [-Wuninitialized]Ausführen:
SpeicherzugriffsfehlerEDIT:
Außerdem (zu den Gettern): Mit Pointern kann man "erwingen" (zumindestens besser als mit Referenzen) das wirklich mit dem Pointer gearbeitet wird. Bei Referenzen:#include <iostream> class X { private: int i; public: void setI(int i) { this->i=i; } int& getIRef() { return i; } int* getIPtr() { return &i; } }; int main() { X myX; myX.setI(5); int *ptr = myX.getIPtr(); *ptr = 6; // myX.i wird direkt bearbeitet. int cpy = myX.getIRef(); // myX.i wird kopiert! int &ref = myX.getIRef(); // so wäre es richtig. cpy = 7; std::cout << myX.getIRef() << std::endl; std::cout << cpy << std::endl; std::cout << ref << std::endl; std::cout << *ptr << std::endl; }
-
pyhax schrieb:
@Videonauth: GCC unter Linux
Compile:22:15: Fehler: »system« wurde in diesem Gültigkeitsbereich nicht definiert [Habe ich rausgemacht 6:5: Warnung: »c« wird in dieser Funktion uninitialisiert verwendet [-Wuninitialized]Ausführen:
SpeicherzugriffsfehlerOoooops ja das mach Booh Booh stimmt, müsste dann so aussehen
#include <iostream> using namespace std; void f (int* ptr) { *ptr=8; } int main() { int a; int b; int* c = &b; f(&a); // mit referenz f(c); // mit zeiger cout<<"Ausgabe: "<< a << endl; cout<<"Ausgabe: "<< b << endl; system("PAUSE"); return 0; }Schreib das grade alles so, ohne IDE im Hintergrund oder Zugriff auf compiler.
-
Irgendwie Blick ich da nicht durch.
Ob ich es jetzt so mache
int glob; int &f ( ) // Mit Referenz { glob = 8; return glob; }oder so:
int glob_2 int *f_2 ( ) // Mit Zeiger { glob_2 = 1; return &glob_2; }Das ist doch intern beides das gleiche.

-
nein. Ein Pointer kann NULL sein, eine Referenz dagegen nicht.
-
cooky451 schrieb:
Gugelmoser schrieb:
cooky451 schrieb:
Getter, Suchfunktionen o.ä. -> Pointer.
Du gibst einen Zeiger auf das Attribut bei Getter zurück? Oder wie meinst du das?
Wenn das Attribut optional ist und keinen "Nullzustand" hat, natürlich. Wie auch sonst?

Und wieso keine Referenz? Das Attribut gibt es doch mit ziemlicher Sicherheit.
CppZgr schrieb:
[...]
Klar, mit beiden Dingen erreichst du dein Ziel. Nichtsdestotrotz sind es zwei völlig verschiedene Typen.
-
Gugelmoser schrieb:
Und wieso keine Referenz? Das Attribut gibt es doch mit ziemlicher Sicherheit.
Hä? Ne, eben nicht, es ist optional.
class a { std::unique_ptr<b> b_; public: a(bool has) : b_(has ? make_unique<b>() : nullptr) {} const b* get_b() { return b_.get(); } };
-
daddy_felix schrieb:
nein. Ein Pointer kann NULL sein, eine Referenz dagegen nicht.
Was ich sagen wollte war das es ja egal ist ob ich es sowie in Bsp. 1 oder sowie in Bsp. 2 mache, da mein Compiler aus beidem intern das gleiche zusammenfrickelt.
Bsp. 1
int glob; int &f ( ) // Mit Referenz { glob = 8; return glob; }Bsp. 2
int glob_2 int *f_2 ( ) // Mit Zeiger { glob_2 = 1; return &glob_2; }
-
was der Compiler daraus macht, ist egal. Es geht um die Anwender deines Codes und um die Möglichkeit, dass die Funktion bei einem Pointer eben auch NULL zurückliefern kann. Somit ist eine zusätzliche Fehlerbehandlung notwendig. Man hat aber die Möglichkeit gewonnen, ein "Fehlschlagen" der Funktion ohne Exceptions zu signalisieren.