const richtig verwenden in C und C++
In dieser Lektion deklarierst du mit dem Schlüsselwort const schreibgeschützte Daten und unterscheidest die Verwendungen von const bei Zeigern.
Einführung
Mit dem Schlüsselwort const kann eine Funktion zusichern, dass sie die übergebenen Daten nicht verändert. Ändert jemand versehentlich Daten, die als const markiert sind, meldet der Compiler sofort einen Fehler. So wird der Code sicherer, und Leser erkennen leichter, welche Funktionen Daten ändern dürfen.
Wichtige Punkte
- Ein Zeiger darf nur auf ein noch existierendes Objekt des richtigen Typs zeigen oder null sein.
- Jeder reservierte Speicherbereich muss genau einmal freigegeben werden.
- Mache deutlich, welche Funktion den Speicher besitzt (ownership) und welche Daten nur gelesen werden (const).
Codebeispiele in C und C++
#include <stdio.h>
int sum(const int *values, size_t count) {
int total = 0;
for (size_t i = 0; i < count; ++i) total += values[i];
return total;
}
int main(void) {
const int values[] = {2, 4, 6};
printf("%d\n", sum(values, 3));
return 0;
}
12
#include <array>
#include <iostream>
int sum(const std::array<int, 3>& values) {
int total = 0;
for (int value : values) total += value;
return total;
}
int main() {
const std::array values{2, 4, 6};
std::cout << sum(values) << '\n';
}
12
C und C++ im Vergleich
Der Parameter const int *values zeigt, dass die Funktion sum die Elemente des Arrays nur liest und nicht ändert. Lies eine Deklaration am besten vom Variablennamen aus nach außen: Ein Zeiger auf const-Daten (const int *) schützt den Wert, auf den er zeigt, ein const-Zeiger (int * const) kann dagegen auf keine andere Adresse umgesetzt werden. C++ kennt außerdem const-Memberfunktionen, die zusichern, den Zustand des Objekts nicht zu ändern.
Besitz und Freigabe von Speicher muss der Programmierer vollständig selbst sicherstellen.
Container und RAII geben Ressourcen automatisch frei, wenn die Lebensdauer des Objekts endet.
Übungen zur Vertiefung
Führe beide Versionen aus und ändere dann den Code, um zu beobachten, welche Sicherheit jede Sprache bietet.
- Teste mit Nullzeigern und fehlgeschlagener Speicherreservierung.
- Führe das Programm mit AddressSanitizer und UndefinedBehaviorSanitizer aus, um Speicherfehler zu finden.
- Notiere klar, welcher Zeiger den Speicher besitzt und welcher nur zum Lesen dient.