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

1

18.02.2015, 22:30

Verständnisproblem zu Listing 11.2 -> const string &sText

Hey liebe Community,

bin grade am lesen des Buches "C++ für Spieleprogrammeirer" von Heiko Kalista und hab mal ne Frage zum Listing 11.2.

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
#include <iostream>

using namespace std;

// Prototypen
//
void ErstelleButton (const string &sText,
                     int Breite = 100, int Hoehe = 30);

// Hauptprogramm
//
int main ()
{
    // Einige Buttons erstellen
    ErstelleButton ("Kleines Icon 1");
    ErstelleButton ("Kleines Icon 2");
    ErstelleButton ("Mittleres Icon", 150, 45);
    ErstelleButton ("Grosses Icon 1", 200, 60);
    ErstelleButton ("Kleines Icon 3");

    return (0);
}

// ErstelleButton
//
void ErstelleButton (const string &sText, int Breite, int Hoehe)
{
    // Ausgabe der Buttoninformationen
    cout << "Folgender Button wurde erstellt: " << endl;
    cout << "Text  : " << sText.c_str() << endl;
    cout << "Breite: " << Breite << endl;
    cout << "Hoehe : " << Hoehe << endl;
    cout << endl;

} // ErstelleButton


Zu meiener Frage: Warum wird für "ErstelleButton" als Parameter "const string &sText" gewählt? Warum nicht einfach "string sText" ? Was soll die Konstante und das kaumännische "und"? Damit wird doch normalerweise eine Referenz angegeben?
Sitze nun Stunden daran und finde keine Lösung für dieses Popelproblem :wacko: :dash:
Auch wenn dieses "const string &sText" eher unnötig ist, würde ich mich über ne Definition freuen :D

Schon mal danke im Voraus!

LG Eizo

2

19.02.2015, 00:39

Wenn du es nicht als Referenz oder Pointer übergeben würdest, müsste davon eine Kopie erstellt werden, was in diesem Fall total unnötig ist und nur zusätzliche Rechenleistung erfordert.

Das const sorgt dafür, dass der String nicht geändert werden kann. In diesem Beispiel könnte man es natürlich problemlos weglassen.
Bei richtigen Programmen, mit höherer komplexität, führt sowas allerdings recht schnell zu einem riesigen "const"-"nicht-const"-Wirrwarr, jeder Menge Compilerfehler, sowie stundenlanges Debugging.
Wieso das so ist und warum man Pointer/Referenzen, wenn möglich, als const deklarieren sollte, ist als Anfänger erstmal schwer zu verstehen. Früher oder später findet man das dann auf die harte Tour raus. Ich versuch es trotzdem mal zu erklären.

Es ist ohne weiteres möglich nicht-const zu const zu casten, allerdings nicht umgekehrt (wenn man mal von const_cast absieht).

C-/C++-Quelltext

1
2
3
4
5
6
7
//nicht-const zu const:
FooBar foobar;
const FooBar* foobarPtr = foobar; //kein Problem

//const zu nicht-const
const FooBar foobar;
FooBar* foobarPtr = foobar; //Fehler


Und genau das, kann sehr schnell Probleme verursachen.
Stell dir z.B. folgendes Szenario vor:

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
#include <string>
#include <iostream>

using namespace std;

void printString(string& str)
{
    cout<<str<<endl;
}

class Foo
{
    public:
        const string& getString() const
        {
            str;
        }

    private:
        string str;
};

int main()
{
    Foo foo;
    printString(foo.getString());
    
    return 0;
}

getString() gibt eine Referenz auf den private Member str zurück. Diese ist natürlich const, weil str nicht von außerhalb geändert werden soll.
Versucht man jetzt diesen String mit printString() auszugeben, bekommt man einen Compilerfehler, da ein const string nicht zu einem normalen string gecastet werden kann.
Wenn man jetzt string& zu const string& ändert, dann würde das Programm ohne weiteres kompilieren:

C-/C++-Quelltext

1
2
3
4
void printString(const string& str)
{
    cout<<str<<endl;
}



Der nächste Grund ist, dass man einer nicht konstanten Referenz keine Objekte direkt übergeben kann.
Um das besser zu erklären, nehme ich nochmal den Code von oben, leicht modifiziert, sodass Foo diesmal keine Referenz zurück gibt, sondern eine Kopie des Strings.

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
#include <string>
#include <iostream>

using namespace std;

void printString(string& str)
{
    cout<<str<<endl;
}

class Foo
{
    public:
        string getString() const
        {
            str;
        }

    private:
        string str;
};

int main()
{
    Foo foo;
    printString(foo.getString());
    
    return 0;
}

Hier bekommt man einen Compilerfehler, der besagt, dass man das string Objekt, das von getString() geliefert wird, nicht direkt an printString() übergeben kann.
Ändert man string& wieder zu const string&, funktioniert es tadellos.
Was ich an dieser Stelle allerdings noch hinzufügen muss ist, dass der Compiler von Microsoft beide Varianten problemlos kompiliert. Andere Compiler machen das nicht.

Es kann also nicht schaden const zu verwenden, auch wenn es überflüssig scheint.
Davon abgesehen, erleichtert es unter Umständen auch das Debugging und vermeidet unnötige Leichtsinnsfehler.
Angenommen man will einen String vergleichen, hat aber versehentlich = statt == geschrieben:

C-/C++-Quelltext

1
2
3
4
5
6
7
void foobar(const std::string& str)
{
   if (str = "test") //Schreibfehler
   {
      //was auch immer
   }
}

In diesem Fall würde der Compiler sofort Alarm schlagen, da str konstant ist. Wäre das nicht so: Happy Debugging!

Ich denke du siehst jetzt, das es so einige Gründe gibt, weshalb man bei solchen Sachen const verwenden sollte.
Wie gesagt, früher oder später wirst du es wahrscheinlich selber merken.

mfg
Marvin

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »Malloc« (19.02.2015, 02:39)