0Pricing
C++ Academy · Lektion

Aufrufbare Objekte auswählen

Lambdas, bind oder Zeiger

Aufrufbare Objekte auswählen ist eine kostenlose C++ Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des C++ Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der C++ Academy-Kurs umfasst insgesamt 4 Lektionen.

Der Werkzeugkasten für aufrufbare Objekte

C++ bietet mehrere Möglichkeiten, Verhalten weiterzugeben: Funktionszeiger, Lambdas, Funktoren, std::bind und std::function. Jedes eignet sich für unterschiedliche Anforderungen.

  • Geschwindigkeit und Flexibilität stehen üblicherweise in einem Spannungsverhältnis.
  • Auch die Lesbarkeit ist wichtig.
#include <iostream>

int twice(int x) { return x * 2; }

int main() {
    int (*fp)(int) = twice;
    auto lam = [](int x) { return x * 2; };
    std::cout << fp(5) << ' ' << lam(5) << '\n';
    return 0;
}

Wann Sie einen Funktionszeiger verwenden sollten

Verwenden Sie einen Funktionszeiger, wenn Sie einen kleinen, zustandslosen Callback benötigen und C-Kompatibilität oder keinen zusätzlichen Laufzeitaufwand wünschen.

#include <iostream>

void logMsg(const char* m) { std::cout << "LOG: " << m << '\n'; }

int main() {
    void (*handler)(const char*) = logMsg;
    handler("started");
    return 0;
}

Wann Sie ein Lambda verwenden sollten

Ein Lambda ist die moderne Standardwahl: Es ist kompakt, kann Zustand erfassen und wird vom Compiler in Templates und Algorithmen gut inline eingesetzt.

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

int main() {
    std::vector<int> v = {3, 1, 4, 1, 5};
    std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
    for (int x : v) std::cout << x << ' ';
    std::cout << '\n';
    return 0;
}

Zustand in einem Lambda erfassen

Lambdas erfassen Variablen aus ihrer Umgebung – etwas, das Funktionszeiger nicht können. Dadurch eignen sie sich ideal für kontextabhängige Callbacks.

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

int main() {
    int threshold = 3;
    std::vector<int> v = {1, 2, 3, 4, 5};
    int c = std::count_if(v.begin(), v.end(), [threshold](int x) { return x > threshold; });
    std::cout << c << '\n';
    return 0;
}

Wann Sie einen Funktor verwenden sollten

Ein Funktor (eine Struktur mit operator()) eignet sich für eine wiederverwendbare, benannte Operation, die Konfiguration enthalten und an vielen Stellen verwendet werden kann.

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

struct AboveThreshold {
    int limit;
    bool operator()(int x) const { return x > limit; }
};

int main() {
    std::vector<int> v = {1, 5, 2, 8};
    std::cout << std::count_if(v.begin(), v.end(), AboveThreshold{4}) << '\n';
    return 0;
}

Lambda oder Bind

Beide können Argumente vorab belegen. Die Lambda-Variante ist normalerweise verständlicher und lässt sich vom Compiler leichter optimieren. Bevorzugen Sie sie daher gegenüber std::bind.

#include <iostream>

int power(int base, int exp) {
    int r = 1;
    for (int i = 0; i < exp; ++i) r *= base;
    return r;
}

int main() {
    auto square = [](int x) { return power(x, 2); };
    std::cout << square(6) << '\n';
    return 0;
}

Wann Sie std::function verwenden sollten

Verwenden Sie std::function, wenn Sie ein aufrufbares Objekt mit unbekanntem konkretem Typ speichern müssen, zum Beispiel als Klassenmember oder in einem Container.

#include <iostream>
#include <functional>
#include <vector>

int main() {
    std::vector<std::function<int(int)>> pipeline;
    pipeline.push_back([](int x) { return x + 1; });
    pipeline.push_back([](int x) { return x * 3; });
    int v = 2;
    for (auto& f : pipeline) v = f(v);
    std::cout << v << '\n';
    return 0;
}

Templates vermeiden zusätzlichen Aufwand

Wenn eine Funktion ein aufrufbares Objekt nur entgegennehmen und nicht speichern muss, sorgt ein Template-Parameter für maximale Geschwindigkeit, da die Typlöschung vermieden wird.

#include <iostream>

template <typename F>
int applyTwice(int x, F f) { return f(f(x)); }

int main() {
    std::cout << applyTwice(3, [](int n) { return n + 10; }) << '\n';
    return 0;
}

Leistungsvergleich

Ungefähr gilt: Ein aufrufbares Objekt aus einem Template oder ein Lambda ohne Erfassung ist am schnellsten, ein Funktionszeiger liegt nur knapp dahinter, und std::function ist wegen der Indirektion und einer möglichen Speicherreservierung am langsamsten.

#include <iostream>
#include <functional>

int main() {
    auto fast = [](int x) { return x + 1; };
    std::function<int(int)> flexible = fast;
    std::cout << fast(1) << ' ' << flexible(1) << '\n';
    return 0;
}

Eine Entscheidungshilfe

Kurze Entscheidungshilfe:

  • Müssen Sie ein beliebiges aufrufbares Objekt speichern? std::function.
  • Nehmen Sie ein solches Objekt nur in einer generischen Funktion entgegen? Template-Parameter.
  • Benötigen Sie Inline-Verhalten mit Zustand? Lambda.
  • C-API oder zustandslos? Funktionszeiger.
#include <iostream>
#include <functional>

void runStored(const std::function<void()>& cb) { cb(); }

template <typename F>
void runGeneric(F f) { f(); }

int main() {
    runStored([] { std::cout << "stored\n"; });
    runGeneric([] { std::cout << "generic\n"; });
    return 0;
}

Alles zusammenführen

Ein kleines Ereignissystem könnte Handler generisch entgegennehmen, sie aber in std::function speichern, damit sie später aufgerufen werden können.

#include <iostream>
#include <functional>
#include <vector>

struct Dispatcher {
    std::vector<std::function<void(int)>> handlers;
    template <typename F> void on(F f) { handlers.emplace_back(f); }
    void fire(int e) { for (auto& h : handlers) h(e); }
};

int main() {
    Dispatcher d;
    d.on([](int e) { std::cout << "got " << e << '\n'; });
    d.fire(7);
    return 0;
}

Schnelltest

Testen Sie Ihr Verständnis der Auswahl aufrufbarer Objekte.

Zusammenfassung

Sie haben gelernt, wie Sie ein aufrufbares Objekt auswählen:

  • Funktionszeiger für zustandslose, C-kompatible Callbacks
  • Lambda als Standard für Inline-Verhalten mit Zustand
  • Funktor für wiederverwendbare, benannte Operationen
  • Template-Parameter, wenn ein aufrufbares Objekt nur entgegengenommen wird (am schnellsten)
  • std::function, wenn Sie ein Objekt mit unbekanntem Typ speichern müssen

Damit ist der Kurs zu Funktionsobjekten und std::bind abgeschlossen.

Häufig gestellte Fragen

Ist die Lektion „Aufrufbare Objekte auswählen“ kostenlos?

Ja — der vollständige Text von „Aufrufbare Objekte auswählen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des C++ Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der C++ Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Aufrufbare Objekte auswählen“?

Lambdas, bind oder Zeiger Du übst C++ Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um C++ Academy zu starten?

Keine Vorkenntnisse erforderlich. C++ Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.

Wie lange dauert die Lektion „Aufrufbare Objekte auswählen“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser C++ Academy-Lektion Code schreiben und ausführen?

Ja. Jede C++ Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Funktionszeiger
  2. std::function
  3. std::bind
  4. Aufrufbare Objekte auswählen
← Zurück zu C++ Academy