Zum Inhalt springen
C++ Anfรคnger 25 min

Variablen & Datentypen

Typen in C++: primitive Typen, auto, const, references vs. values, und Standard-Library-Typen wie std::string und std::vector.

Aktualisiert:
Inhaltsverzeichnis

Variablen & Datentypen

C++ ist statisch und stark typisiert - Typen werden zur Kompilierzeit festgelegt. Dank auto musst du Typen selten explizit ausschreiben.

Variablen deklarieren

int alter = 28;
double pi = 3.14159;
bool aktiv = true;
std::string name = "Anna";

Mit Initialisierungslisten (empfohlen)

int alter{28};
double pi{3.14159};
std::string name{"Anna"};

Diese {}-Syntax (Braced Init) verhindert Narrowing - etwa eine double in einen int zu stopfen und dabei Nachkommastellen zu verlieren:

int x = 3.7;    // OK - wird 3 (Narrowing!)
int y{3.7};      // FEHLER - Narrowing verhindert

Mit auto

auto alter = 28;                 // int
auto pi = 3.14;                  // double
auto name = std::string{"Anna"};  // std::string

const, constexpr und consteval

const int MAX = 100;              // Laufzeitkonstante
constexpr int SECONDS_PER_DAY = 86400;  // Kompilierzeit-konstant

constexpr int square(int x) {
    return x * x;
}

int arr[square(5)];   // OK - 25 ist zur Kompilierzeit bekannt

Faustregel: Wenn du den Wert zur Kompilierzeit kennst, nimm constexpr. Sonst const. Beide sind dem Compiler willkommen fuer Optimierung.

Primitive Typen

Ganzzahlen

int a = 42;                // typischerweise 32-Bit
long b = 42L;
long long c = 42LL;
unsigned int d = 42U;
short e = 42;

Fuer groessenexakte Typen aus <cstdint>:

#include <cstdint>

int32_t x = 42;
int64_t y = 1'000'000'000LL;
uint8_t z = 255;

Die ' sind Ziffern-Trennzeichen seit C++14, reiner Lesekomfort.

Fliesskomma

float f = 3.14f;
double d = 3.14159;
long double ld = 3.14159L;

double ist der Standard (64 Bit).

Boolean

bool aktiv = true;
bool fertig = false;

Character

char c = 'A';             // 1 Byte
char16_t c2 = u'A';       // UTF-16
char32_t c3 = U'๐Ÿฆ€';      // UTF-32

Strings

Vermeide nackte char* oder char[] - nutze std::string:

#include <string>

std::string name = "Anna";
name += " Mueller";                 // Verkettung
std::string gruss = "Hallo, " + name;

// Methoden
name.length();                      // 12
name.substr(0, 4);                  // "Anna"
name.find("Mueller");                // Position
name.empty();                        // false

String-Views (schnell, ohne Kopie)

#include <string_view>

void verarbeite(std::string_view text) {
    // Keine Kopie, nur ein "Fenster" auf Original-Daten
}

std::string s = "Hallo";
verarbeite(s);           // implizite Konvertierung
verarbeite("Welt");      // funktioniert auch mit const char*

Fuer Funktionsparameter, die nur lesen, ist std::string_view ideal.

Container aus der STL

std::vector - dynamisches Array

#include <vector>

std::vector<int> zahlen = {1, 2, 3, 4, 5};
zahlen.push_back(6);           // anhaengen
zahlen[0] = 99;
std::cout << zahlen.size();    // 6

Gleichwertige moderne Alternative fuer int zahlen[5]. Nutze fast immer std::vector.

std::array - Array fester Groesse

#include <array>

std::array<int, 3> punkte = {10, 20, 30};

Bessere Variante als C-Arrays, mit size(), Iteration, etc.

std::map und std::unordered_map

#include <map>
#include <unordered_map>

std::map<std::string, int> alter = {
    {"Anna", 28},
    {"Max", 34}
};

std::cout << alter["Anna"];    // 28
alter["Leo"] = 22;

// Unordered ist schneller (Hash), aber unsortiert
std::unordered_map<std::string, int> counts;

std::pair

#include <utility>

std::pair<int, std::string> p = {1, "Anna"};
std::cout << p.first << ", " << p.second;

std::optional

Wenn ein Wert fehlen kann:

#include <optional>

std::optional<int> finde(int id) {
    if (id > 0) return 42;
    return std::nullopt;   // "nicht vorhanden"
}

auto ergebnis = finde(1);
if (ergebnis) {
    std::cout << *ergebnis;
}

References vs. Pointers

Value

void funktion1(int x) { ... }  // Kopie - teuer bei grossen Objekten

Reference

void funktion2(int& x) { ... }         // kann veraendern
void funktion3(const int& x) { ... }   // kann nicht veraendern

Die const&-Variante ist der Standard fuer grosse Objekte:

void druckeName(const std::string& name) {
    std::cout << name << "\n";
}

Pointer

int x = 42;
int* p = &x;         // Pointer auf x
*p = 100;            // Dereferenzieren und aendern
std::cout << x;      // 100

Pointers koennen null sein, Referenzen nicht. Moderne C++-Empfehlung: bevorzuge Referenzen, nutze Pointer (oder Smart Pointer) nur wenn noetig.

Typ-Konvertierung

Implizit

int x = 5;
double d = x;   // OK - int -> double

Explizit mit static_cast

double d = 3.7;
int x = static_cast<int>(d);   // 3

static_cast ist der moderne Weg statt C-Style-Cast (int)d.

String zu Zahl

int zahl = std::stoi("42");        // wirft Exception bei Fehler
double d = std::stod("3.14");

// Sicherer mit <charconv> (C++17+)
#include <charconv>

int wert;
auto ergebnis = std::from_chars(str.data(), str.data() + str.size(), wert);
if (ergebnis.ec != std::errc{}) {
    // Fehler
}

Enum Classes

Moderne, typsichere Enums:

enum class Richtung { Nord, Sued, Ost, West };

Richtung r = Richtung::Nord;

if (r == Richtung::Nord) {
    std::cout << "Nordwaerts!\n";
}

Bevorzuge enum class gegenueber klassischem enum - keine Namenskonflikte, Typ-sicher.

Praktisches Beispiel

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

int main() {
    struct Person {
        std::string name;
        int alter;
    };

    std::vector<Person> leute = {
        {"Anna", 28},
        {"Max", 34},
        {"Leo", 22}
    };

    // Nach Alter sortieren
    std::sort(leute.begin(), leute.end(),
              [](const Person& a, const Person& b) {
                  return a.alter < b.alter;
              });

    for (const auto& p : leute) {
        std::cout << p.name << " (" << p.alter << ")\n";
    }
}

Zusammenfassung

  • Braced Init (int x{42}) verhindert Narrowing - nutze sie als Default
  • auto fuer Typ-Inferenz, const/constexpr fuer Konstanten
  • Primitiv-Typen plus Standard-Library (std::string, std::vector, std::map)
  • const T& fuer Funktionsparameter, die nur lesen
  • enum class statt klassische enum
  • static_cast statt C-Style-Cast

Im naechsten Kapitel: Kontrollstrukturen.

Zurรผck zum C++ Kurs