Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

AriesT

Frischling

  • »AriesT« ist der Autor dieses Themas

Beiträge: 24

Wohnort: Bei Frankfurt

Beruf: Azubi IT Kaufmann

  • Private Nachricht senden

1

13.07.2009, 19:07

[Kapitel 6] Aufgabe - Verständnis von Refs, Zeiger, Funktion

Hallo Leute,
habe mir vor einem Monat das C++ Buch gekauft und nun stecke ich fest. Bzw. ich stelle fest, dass mir das Tempo zwischen Kapitel 4 und 6 zu hoch geworden ist und ich nicht alles verstanden habe.

Ich bin mittlerweile komplett verwirrt was Funktionen, Aufruf der Funktionen, Wertübergabe angeht und die Regeln, wann man einen Wert, Zeiger oder Referenz übergibt, habe ich auch nicht verstanden.
Diese Themen sind mir im Buch etwas zu schwammig erklärt, bzw. ich verstehe sie anhand der Beispiele und Erklärungen nicht.

Meine Lösung funktioniert zwar, aber sie ist komplett anders, als die Lösung im Buch, vor allem was die Nutzung von Referenz und Zeiger anngeht, eben weil ich das nicht verstanden habe:


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>

using namespace std;

//Strukturen

struct sSpieler
{
    int Energie;
    int Punkte;
    int Team;
};

//Prototypen

void BerechnePunkte(sSpieler *pSpieler, int Bonus);
void ZeigeSpieler(sSpieler *pSpieler);
void LadeLevel(const int Level);

int main ()
{
    //Instanzen

    sSpieler Spieler1;

    //Variablen

    int Bonus = 300;
    const int Level = 1;

    //Spieler Werte initialisieren

    Spieler1.Energie = 100;
    Spieler1.Punkte = 0;
    Spieler1.Team = 2;

    //Funktionen aufrufen

    LadeLevel(Level);
    ZeigeSpieler(&Spieler1);
    BerechnePunkte(&Spieler1, Bonus);
    ZeigeSpieler(&Spieler1);

return 0;
}

//Punkte berechnen

void BerechnePunkte(sSpieler *pSpieler, int Bonus)
{
    pSpieler->Punkte += Bonus;
}

//Spielerdaten zeigen

void ZeigeSpieler(sSpieler *pSpieler)
{
    cout <<"Werte des Spielers:"<<endl;
    cout <<"Energie: "<<pSpieler->Energie<<endl;
    cout <<"Punkte: "<<pSpieler->Punkte<<endl;
    cout <<"Team: "<<pSpieler->Team<<"\n\n"<<endl;
}

//Level laden

void LadeLevel(const int Level)
{
    cout <<"Level "<<Level<<" geladen.\n"<<endl;
}


Vielleicht kann mir jemand das ganze nochmal so erklären, dass ich das auch richtig kapiere.

n0_0ne

1x Contest-Sieger

  • Private Nachricht senden

2

13.07.2009, 19:23

Also erstmal willkommen im Forum...
Aber trotzdem ist dein Start nicht sehr gelungen ;) Ich finde es übertrieben von dir, zu erwarten, dass wir uns jetzt hier hinsetzen und nochmal Kapitel 4-6 des Buches erklären... Google spuckt zu Call by Value/Reference und pointern ne Menge aus. Also entweder du stellst jetzt konkrete Fragen, oder du musst dir selbst helfen ^^

AriesT

Frischling

  • »AriesT« ist der Autor dieses Themas

Beiträge: 24

Wohnort: Bei Frankfurt

Beruf: Azubi IT Kaufmann

  • Private Nachricht senden

3

13.07.2009, 19:37

Ich dachte, die indirekten Fragen wären deutlich im oberen Abschnitt. :(

Ok, um es zu konkretisieren:
Wann nehme ich bei Funktionen den Wert, wann den Zeiger, wann die Referenz?
Was muss im jeweiligen Falle im Prototyp / Funktion und was im Aufruf in der Hauptfunktion stehen (als Parameter).

Nehmen wir die Funktion: "Beispiel" zum Beispiel. (Was ein Wortspiel)

void Beispiel(....);

Und bitte nicht direkt mit Google anfangen, das habe ich jetzt in jedem besch...eidenen Forum lesen müssen. Da sind ide Erklärungen meist viel schlechter als im Buch. Deswegen hab ich mich ja extra an ein Spieleprogrammierer Forum gewandt.

In allen anderen Foren kommen dann Sprüche ala: "Du bist blöd, lass es gleich ganz bleiben. Such bei Google." Ohne auf mich einzugehe. Ich nehme doch stark an, das ist in diesem Forum nicht so. ;)


EDIT: Wie gesagt, ich habe vor allem die "Wert, Zeiger, Referenz" Regeln nicht verstanden, die im Buch direkt vor der Aufgabenstellung stehen.

physX

Treue Seele

Beiträge: 119

Wohnort: Dresden

  • Private Nachricht senden

4

13.07.2009, 20:05

Hallo, also im Buch Seite 174 ist eine wie ich finde gute Anleitung zur Verwendung von Werten,Zeigern bzw. Referenzen.

auf dein Beispiel bezogen:

ZeigeSpieler(const Spieler &Spieler) -> Übergabe als Referenz, da die Funktion nichts an den den Werten/Variablen der Struktur Spieler ändert und auch nicht änder soll. Zur Sicherheit wird das ganze const übergeben; so kann auch wirklich nichts passieren.

BerechnePunkte(Spieler *pSpieler) -> hier sollen konkret Werte aus deiner Spielerklasse/Struktur verändert werden. Daher wird deine Instanz als Zeiger an die funktion übergeben.

Referenz und Zeiger sind ähnlich beide zeigen jeweils nur auf die Adresse in der die Variable/Klasse gespeichert ist.

hoffe das hilft. Ansonsten einfach mal das Buch nen tag zur Seite legen und dann das Kapitel nochmal in aller Ruhe durchlesen. Das hilft oft... :)
Gruss

AriesT

Frischling

  • »AriesT« ist der Autor dieses Themas

Beiträge: 24

Wohnort: Bei Frankfurt

Beruf: Azubi IT Kaufmann

  • Private Nachricht senden

5

13.07.2009, 20:21

Erstmal danke, dass Du dir Zeit genommen hast, mir zu antworten. Ich bin auch glaube ich etwas weitergekommen. :D

Also, wenn ich es jetzt richtig verstanden habe, knapp zusammengefasst lässt sich sagen:

----
Zeiger als Parameter -> Ein Wert soll verändert werden
Referenz als Parameter -> Der Wert soll NICHT verändert werden.
Aber Wert als Parameter -> ???
----

Wozu soll ich noch normale Werte übergeben, wenn ich unveränderte Werte auch per Referenz aufrufen kann? Z.B. im Listing 6.9.
Da kann ich "Bonus = 550;" schreiben, per Referenz aufrufen und komme aufs gleiche hinaus.
Verstehe nicht, was Heiko damit sagen möchte bzw. warum er hier einen Wert übergibt anstelle einer Referenz.


Das zweite "HÄ?" tritt bei mir allerdings auch bei den Referenzen auf. Zumindest was die Anwendung in der Realität angeht.

Was bringen mir Referenzen in der Praxis? Es wäre mit aktuellem Wissensstand "nur" sinnvoll eine Referenz der Funktion zu übergeben, wenn man irgendeine Gruppe von Werten cout<< machen möchte. Für etwas anderes sehe ich z.Z. keine Verwendung.

Das verwirrt mich noch etwas.

physX

Treue Seele

Beiträge: 119

Wohnort: Dresden

  • Private Nachricht senden

6

13.07.2009, 20:44

Zitat von »"AriesT"«

Erstmal danke, dass Du dir Zeit genommen hast, mir zu antworten. Ich bin auch glaube ich etwas weitergekommen. :D

Also, wenn ich es jetzt richtig verstanden habe, knapp zusammengefasst lässt sich sagen:

----
Zeiger als Parameter -> Ein Wert soll verändert werden
Referenz als Parameter -> Der Wert soll NICHT verändert werden.
Aber Wert als Parameter -> ???
----

Wozu soll ich noch normale Werte übergeben, wenn ich unveränderte Werte auch per Referenz aufrufen kann? Z.B. im Listing 6.9.
Da kann ich "Bonus = 550;" schreiben, per Referenz aufrufen und komme aufs gleiche hinaus.
Verstehe nicht, was Heiko damit sagen möchte bzw. warum er hier einen Wert übergibt anstelle einer Referenz.


Das zweite "HÄ?" tritt bei mir allerdings auch bei den Referenzen auf. Zumindest was die Anwendung in der Realität angeht.

Was bringen mir Referenzen in der Praxis? Es wäre mit aktuellem Wissensstand "nur" sinnvoll eine Referenz der Funktion zu übergeben, wenn man irgendeine Gruppe von Werten cout<< machen möchte. Für etwas anderes sehe ich z.Z. keine Verwendung.

Das verwirrt mich noch etwas.


Bei Zeigern und Referenzen geht es ja insbesondere auch darum, dass bei der Übergabe einer Klasse nicht immer die komplette Klasse im Speicher kopiert werden muss (das passiert wenn du die Klasse NICHT als Zeiger oder Referenz übergibst). Übergibst du eine Referenz oder einen Zeiger dann wird nur die Adresse wo die Daten gespeichert sind übergeben. Das geht schneller und kostet nicht soviel zusätzlichen Speicher (nur die adresse selbst wird kopiert und zwischengespeicher).

bei werten, also int/float/bool etc. ist der Unterschied beim übergeben im Vergleich zur Übergabe als Zeiger/Referenz unwesentlich. Daher wird ein Wert, den man nicht ändern möchte einfach ganz normal übergeben.

Gruss

AriesT

Frischling

  • »AriesT« ist der Autor dieses Themas

Beiträge: 24

Wohnort: Bei Frankfurt

Beruf: Azubi IT Kaufmann

  • Private Nachricht senden

7

13.07.2009, 20:49

Achso, also kann man sagen, dass man Zeiger und Referenzen überwiegend bei Strukturen und Klassen (bin ich noch nicht, kommt ja erst in K7) übergibt.

Zitat


Struktur / Klasse
{
int bla;
float blubb;
char Döng[100.000];
}

bei sowas

Während man eine Wertübergabe meist nur dann macht, wenn er für sich alleine steht.
Also wenn jetzt irgendwo in der main() Funktion die Variable "Wert = 10;" auftaucht, dass man idR nur dann eine Wertübergabe macht.

n0_0ne

1x Contest-Sieger

  • Private Nachricht senden

8

13.07.2009, 20:55

bei den nativen datentypen wäre der unterschied zum zeiger nichtmal unwesentlich. ein zeiger würde durch die zusätzliche indirektion noch zusätzlichen overhead erzeugen, wirkt sich also negativ auf die performance aus.

Ich bin mir nicht wirklich sicher wie genau ein compiler referencen in assembler übersetzt, aber im kontext von c++ werden sie eigentlich nicht wie pointer gehandhabt (müssen eigentlich nicht z.B. mit * dereferenziert werden). sie sind mehr oder weniger ein alias. meiner meinung nach eine mischung zwischen den normalen werten und pointern.

AriesT

Frischling

  • »AriesT« ist der Autor dieses Themas

Beiträge: 24

Wohnort: Bei Frankfurt

Beruf: Azubi IT Kaufmann

  • Private Nachricht senden

9

13.07.2009, 21:09

Danke, dass Du Verständnis für Anfänger hast und mit Fachbegriffen um Dich wirfst. :lol:

Jetzt bin ich wieder verwirrt. :oops:
Indirektion? Overhead? Compiler Dingens? What? Sorry, ich habs nicht so mit Fachbegriffen und compiler-internen Abläufen, weil ich erst seit einem Monat damit hantiere.

Kannst Du deinen Kommentar bitte noch einmal in einfacher Sprache wiederholen?

Also Physx hat es geschafft, mir Deppen das Thema einigermaßen verständlich zu erklären, jetzt hätte ich gerne nur eine Bestätigung für meine Beispiele oder ein "Nein, die Beispiele sind so nicht richtig, weil..." um nicht noch gefrusteter zu sein, als ich es jetzt schon bin.

Danke euch. ;)

Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

10

13.07.2009, 21:29

Was n0_0ne sagen wollte:
Bei "normalen" Datentypen (also bool, char, float, int, etc ) sind Referenzen und Zeiger langsamer als die normale übergabe als Wert.

Das kann man sich so vorstellen:
Übergabe als Wert:
Kopiere Wert von Variable nach Parameter

Bei einer Referenz/Zeiger kommt aber noch ein Schritt dazu:
Erstelle Zeiger auf Variable
Kopiere Wert von Zeiger nach Parameter

Du hast also bei Zeigern zwei Schritte die beide in etwa die gleiche Zeit brauchen. Das heißt du verdoppelts die Zeit die es dauert bis der Wert an deinem Parameter angekommen ist (ja verdoppeln wahrscheinlich nicht, aber er wollts einfach haben ;)). Bei großen Datentypen (also eigenen Klassen und Strukturen) ist es aber immernoch schneller diese beiden Schritte auszuführen, als die komplette klasse einmal zu kopieren

Werbeanzeige