Skip to content

02 Zeiger und Arrays

gideon edited this page Oct 24, 2024 · 2 revisions

Zusammenfassung der Slides "Zeiger und Arrays" mit passenden Codebeispielen

1. Zeiger in C/C++

Ein Zeiger zeigt auf eine Speicherstelle im virtuellen Adressraum. Der Speicherbedarf eines Zeigers hängt von der Plattform ab (32 Bit auf x86, 64 Bit auf x64). Zeiger sind stark typisiert, und der Adressoperator (&) gibt die Speicheradresse einer Variablen zurück, während der Dereferenzierungsoperator (*) auf den Wert zugreift, auf den der Zeiger zeigt.

Beispiel für Zeiger:

int x = 5;          // x wird mit 5 initialisiert
int* px = &x;       // px zeigt auf x
*px = 7;            // Wert von x wird auf 7 gesetzt
std::cout << x;     // Ausgabe: 7

2. Smart-Pointer in C++

Smart-Pointer sind spezielle Zeigerobjekte, die den Speicher automatisch verwalten. Dazu verwenden sie Referenzzähler, um festzustellen, wann ein Objekt nicht mehr benötigt wird, und geben den Speicher dann automatisch frei.

2.1 std::unique_ptr

std::unique_ptr besitzt genau einen Besitzer für ein Objekt. Sobald der Besitzer zerstört wird, wird auch das Objekt zerstört.

Beispiel für std::unique_ptr:

#include <memory>

std::unique_ptr<int> p = std::make_unique<int>(10);
std::cout << *p << std::endl;  // Ausgabe: 10

2.2 std::shared_ptr

std::shared_ptr kann mehrere Besitzer für ein Objekt haben. Ein Referenzzähler stellt sicher, dass das Objekt erst dann gelöscht wird, wenn kein Besitzer mehr existiert.

Beispiel für std::shared_ptr:

#include <memory>

std::shared_ptr<int> p1 = std::make_shared<int>(20);
std::shared_ptr<int> p2 = p1;  // p1 und p2 besitzen dasselbe Objekt
std::cout << *p1 << std::endl; // Ausgabe: 20

3. C-Arrays und C-Strings in C/C++

C-Arrays sind eindimensionale Datenstrukturen mit einer festen Länge, die nicht im Array selbst gespeichert wird. C-Strings sind spezielle Arrays vom Typ char, die mit einem Null-Byte (\0) terminiert werden.

Beispiel für ein C-Array:

int arr[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; ++i) {
    std::cout << arr[i] << " ";  // Ausgabe: 1 2 3 4 5
}

Beispiel für einen C-String:

char str[] = "Hallo";
std::cout << str << std::endl;  // Ausgabe: Hallo

4. Arrays und Strings in C++

In modernem C++ stehen std::array und std::vector zur Verfügung, die einige der Einschränkungen von C-Arrays beheben.

Beispiel für std::array:

#include <array>

std::array<int, 4> arr = {1, 2, 3, 4};
for (int val : arr) {
    std::cout << val << " ";  // Ausgabe: 1 2 3 4
}

Beispiel für std::vector:

#include <vector>

std::vector<int> vec = {1, 2, 3, 4, 5};
vec.push_back(6);
for (int val : vec) {
    std::cout << val << " ";  // Ausgabe: 1 2 3 4 5 6
}

5. Zeiger und const

Zeiger können mit dem Schlüsselwort const kombiniert werden, um entweder den Zeiger selbst oder das Ziel, auf das der Zeiger zeigt, als unveränderbar zu deklarieren.

Beispiel für const-Zeiger:

int x = 10;
const int* p1 = &x;    // p1 ist ein Zeiger auf einen konstanten Integer
int* const p2 = &x;    // p2 ist ein konstanter Zeiger auf einen Integer
const int* const p3 = &x; // p3 ist ein konstanter Zeiger auf einen konstanten Integer

6. Smart-Pointer Ownership Konzepte

  • std::unique_ptr: Nur ein Besitzer pro Objekt, gut geeignet für den exklusiven Besitz.
  • std::shared_ptr: Mehrere Zeiger können auf dasselbe Objekt zeigen. Das Objekt wird gelöscht, wenn kein shared_ptr mehr darauf verweist.
  • std::weak_ptr: Schwacher Zeiger, der nicht zur Referenzzählung beiträgt. Verwendet, um zyklische Abhängigkeiten zu vermeiden.

7. Zeigerarithmetik

Zeigerarithmetik ermöglicht das Navigieren durch Speicherbereiche mithilfe von Zeigern. Erlaubte Operationen sind u. a. +, -, ++ und --. Dabei berücksichtigt der Compiler die Größe des Datentyps, auf den der Zeiger zeigt.

Beispiel für Zeigerarithmetik:

int arr[5] = {10, 20, 30, 40, 50};
int* p = arr;

for (int i = 0; i < 5; ++i) {
    std::cout << *(p + i) << " ";  // Ausgabe: 10 20 30 40 50
}

8. C++ Strings und Rohstringliterale

C++ bietet die Klasse std::string als komfortablere Alternative zu C-Strings. Rohstringliterale (R"(text)") ermöglichen die einfache Darstellung von Zeichenketten, die Sonderzeichen enthalten.

Beispiel für einen std::string:

#include <string>

std::string name = "Andrea";
std::cout << name << std::endl;  // Ausgabe: Andrea

Beispiel für ein Rohstringliteral:

const char* raw = R"(<HTML>
<HEAD>
<TITLE>Beispiel</TITLE>
</HEAD>
</HTML>)";
std::cout << raw << std::endl;

9. std::span in C++

std::span bietet eine Möglichkeit, auf eine Sequenz von Daten zuzugreifen, ohne diese zu kopieren. Es kann für C-Arrays, std::array oder std::vector verwendet werden.

Beispiel für std::span:

#include <span>
#include <vector>

std::vector<int> v = {1, 2, 3, 4, 5};
std::span<int> s = v;

for (int val : s) {
    std::cout << val << " ";  // Ausgabe: 1 2 3 4 5
}

Diese Zusammenfassung bietet eine grundlegende Einführung in Zeiger, Arrays und Strings in C++, einschließlich der modernen Ansätze zur Speicherverwaltung mithilfe von Smart-Pointern. Sie beleuchtet die wichtigsten Konzepte und deren praktische Anwendung mit Beispielen.