Puntatori a funzione e callback in C e C++
In questa lezione passerai una funzione come parametro a un'altra funzione con i puntatori a funzione in C e le lambda in C++.
Introduzione
Il callback è la tecnica di passare una funzione a un'altra funzione, che la richiama quando serve. Così un algoritmo generico può eseguire il comportamento scelto da chi lo chiama senza conoscere i dettagli di implementazione. Per esempio, la stessa funzione apply può elevare al quadrato, raddoppiare o fare qualsiasi altra trasformazione.
Punti importanti
- Un puntatore deve puntare solo a un oggetto che esiste ancora, del tipo giusto, oppure essere nullo.
- Ogni area di memoria allocata va liberata esattamente una volta.
- Rendi chiaro quale funzione possiede la memoria (ownership) e quali dati sono solo letti (const).
Esempi di codice C e C++
#include <stdio.h>
int square(int value) { return value * value; }
int apply(int value, int (*operation)(int)) { return operation(value); }
int main(void) {
printf("%d\n", apply(6, square));
return 0;
}
36
#include <functional>
#include <iostream>
int apply(int value, const std::function<int(int)>& operation) {
return operation(value);
}
int main() {
int factor = 6;
std::cout << apply(factor, [](int value) { return value * value; }) << '\n';
}
36
Confronto tra C e C++
In C, il parametro int (*operation)(int) è un puntatore a funzione che accetta funzioni con un parametro int e un valore di ritorno int, quindi apply(6, square) restituisce 36. In C++, le lambda e std::function possono contenere una varietà più ampia di oggetti richiamabili (callable). Nel codice che richiede alte prestazioni, i template sono spesso una scelta migliore di std::function.
Il possesso e la liberazione della memoria sono interamente a carico del programmatore.
Contenitori e RAII liberano automaticamente le risorse quando l'oggetto arriva alla fine della sua vita.
Esercizi di approfondimento
Esegui entrambe le versioni e poi modifica il codice per osservare la differenza di sicurezza che offre ciascun linguaggio.
- Prova con puntatori nulli e allocazioni di memoria fallite.
- Esegui il programma con AddressSanitizer e UndefinedBehaviorSanitizer per trovare errori di memoria.
- Annota chiaramente quale puntatore possiede la memoria e quale serve solo per leggere.
Esercitati con una sfida
Usa ciò che questa lezione spiega per risolvere un problema reale. Ogni sfida gira nel browser, con test immediati e una revisione dell'IA.
- Funzioni di attivazione Applica sigmoide, ReLU, Leaky ReLU o tanh a ogni valore di una lista. Facile