Funktionale Programmierung in C++: von A bis Z – ein praktischer Leitfaden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Funktionale Programmierung in C++: von A bis Z



Viele Entwickler, die mit Python oder JavaScript vertraut sind, kennen die leistungsstarken Werkzeuge der funktionalen Programmierung: Lambdas, map, filter, reduce. Aber wussten Sie, dass C++ nicht weniger flexible Möglichkeiten für den funktionalen Stil bietet? In diesem Artikel werden wir die funktionale Programmierung in C++ von den grundlegenden Konzepten bis zu fortgeschrittenen Techniken durchgehen. Sie erfahren, wie Sie mit den modernen Funktionen von C++11/14/17 prägnanteren, sichereren und ausdrucksstärkeren Code schreiben können.



1. Grundlagen des funktionalen Ansatzes: Lambda-Ausdrücke und std::function



Funktionale Programmierung in C++ beginnt mit Lambda-Ausdrücken. Sie ermöglichen es, anonyme Funktionen direkt am Verwendungsort zu erstellen. Die Syntax eines Lambdas ist einfach:



// Basis-Lambdaauto sum = [](int a, int b) -> int { return a + b; };std::cout << sum(5, 3); // 8

// Lambda mit Variablen-Captureint multiplier = 3;auto multiply = [multiplier](int x) { return x * multiplier; };std::cout << multiply(7); // 21


Das entscheidende Merkmal von Lambdas ist der Kontext-Capture. Sie können Variablen per Wert ([=]), per Referenz ([&]) oder kombiniert erfassen. Dies ist die Grundlage von Closures, die das Fundament des funktionalen Stils bilden.



Zum Speichern und Übergeben von Lambdas wird std::function verwendet – ein polymorpher Wrapper für aufrufbare Objekte:



#include <functional>

std::function<int(int, int)> operation;

operation = [](int a, int b) { return a + b; };std::cout << operation(10, 20); // 30

operation = [](int a, int b) { return a * b; };std::cout << operation(10, 20); // 200


Tipp: Verwenden Sie auto für Lambdas, wenn Sie sie nicht als Typ speichern müssen. std::function fügt einen geringen Overhead hinzu, daher sollte es nur bei Bedarf an Polymorphie eingesetzt werden.



2. STL-Algorithmen: map, filter, reduce selbst gemacht



In C++ gibt es keine eingebauten Funktionen map, filter, reduce wie in Python, aber die STL bietet leistungsstarke Algorithmen, die diese ersetzen. Betrachten wir die wichtigsten:



2.1. Map – Transformation von Elementen

Statt map verwenden Sie std::transform:



#include <algorithm>#include <vector>

std::vector<int> numbers = {1, 2, 3, 4, 5};std::vector<int> squares(numbers.size());

std::transform(numbers.begin(), numbers.end(), squares.begin(), [](int n) { return n * n; });// squares: {1, 4, 9, 16, 25}


2.2. Filter – Filtern nach Bedingung

Das Äquivalent zu filter ist std::copy_if oder std::remove_if (mit anschließendem Löschen):



std::vector<int> numbers = {1, 2, 3, 4, 5, 6};std::vector<int> evens;

std::copy_if(numbers.begin(), numbers.end(), std::back_inserter(evens), [](int n) { return n % 2 == 0; });// evens: {2, 4, 6}


2.3. Reduce – Faltung einer Sammlung

Für reduce verwenden Sie std::accumulate aus <numeric>:



#include <numeric>

std::vector<int> numbers = {1, 2, 3, 4, 5};int sum = std::accumulate(numbers.begin(), numbers.end(), 0, [](int acc, int n) { return acc + n; });// sum = 15


Fortgeschrittenes Beispiel: Kombinieren von map, filter und reduce zur Datenverarbeitung:



std::vector<std::string> names = {"Alice", "Bob", "Charlie", "David"};// Summe der Längen von Namen, die mit 'A' oder 'C' beginnenint result = std::accumulate(names.begin(), names.end(), 0,    [](int acc, const std::string& name) {        if (name[0] == 'A' || name[0] == 'C') {            return acc + name.length();        }        return acc;                

Blogs

Buchempfehlungen