Scegliere i callable
Lambda, bind o puntatori
Scegliere i callable è una lezione C++ Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C++ Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C++ Academy include 4 lezioni in totale.
La cassetta degli attrezzi dei callable
Il C++ offre diversi modi per passare i comportamenti: puntatori a funzione, lambda, functor, std::bind e std::function. Ognuno è adatto a esigenze diverse.
- Il compromesso abituale è tra velocità e flessibilità.
- Anche la leggibilità è importante.
#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;
}Quando usare un puntatore a funzione
Scelga un puntatore a funzione quando ha bisogno di una piccola callback senza stato e desidera la compatibilità con il C o un overhead nullo.
#include <iostream>
void logMsg(const char* m) { std::cout << "LOG: " << m << '\n'; }
int main() {
void (*handler)(const char*) = logMsg;
handler("started");
return 0;
}Quando usare una lambda
Una lambda è la scelta predefinita nel C++ moderno: è concisa, può catturare lo stato e il compilatore la integra bene nei template e negli algoritmi.
#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;
}Catturare lo stato in una lambda
Le lambda catturano le variabili circostanti, cosa che i puntatori a funzione non possono fare, e sono quindi ideali per callback sensibili al contesto.
#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;
}Quando usare un functor
Un functor (una struct con operator()) è adatto a un'operazione riutilizzabile e denominata, che può contenere una configurazione ed essere usata in più punti.
#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 o bind
Entrambi consentono di preimpostare gli argomenti. La versione con lambda è generalmente più chiara e più facile da ottimizzare per il compilatore, quindi la preferisca a 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;
}Quando usare std::function
Usi std::function quando deve memorizzare un oggetto chiamabile di tipo concreto sconosciuto, ad esempio in un membro di classe o in un contenitore.
#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;
}I template evitano l'overhead
Se una funzione deve solo ricevere un oggetto chiamabile, senza memorizzarlo, un parametro template mantiene le massime prestazioni evitando il type erasure.
#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;
}Classifica delle prestazioni
In linea di massima: un oggetto chiamabile basato su template o una lambda senza catture sono le soluzioni più veloci, un puntatore a funzione è quasi altrettanto veloce e std::function è il più lento a causa dell'indirezione e della possibile allocazione.
#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;
}Una guida alla scelta
Guida rapida:
- Deve memorizzare un oggetto chiamabile qualsiasi?
std::function. - Deve solo riceverne uno in una funzione generica? Un parametro template.
- Comportamento inline con stato? Lambda.
- API C o comportamento senza stato? Puntatore a funzione.
#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;
}Mettere insieme tutti gli elementi
Un piccolo sistema di eventi potrebbe ricevere i gestori in modo generico, ma memorizzarli in std::function per poterli invocare in seguito.
#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;
}Verifica rapida
Verifichi la Sua comprensione della scelta degli oggetti chiamabili.
Riepilogo
Ha imparato a scegliere un oggetto chiamabile:
- puntatore a funzione per callback senza stato e compatibili con il C
- lambda come scelta predefinita per comportamenti inline con stato
- functor per operazioni denominate e riutilizzabili
- parametro template quando deve solo ricevere un oggetto chiamabile, con le massime prestazioni
std::functionquando deve memorizzare un oggetto di tipo sconosciuto
Ha completato il corso sugli oggetti funzione e std::bind.
Impara C++ con un tutor IA — gratis
Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.
- Corsi
- 51
- Lezioni
- 203
Domande Frequenti
La lezione «Scegliere i callable» è gratuita?
Sì — il testo completo di «Scegliere i callable» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C++ Academy, passa a CoddyKit PRO. Il corso C++ Academy include 4 lezioni in totale.
Cosa imparerò in «Scegliere i callable»?
Lambda, bind o puntatori Eserciti C++ Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare C++ Academy?
Non è richiesta alcuna esperienza precedente. C++ Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Scegliere i callable»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione C++ Academy?
Sì. Ogni lezione C++ Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Puntatori a funzione
- std::function
- std::bind
- Scegliere i callable