Ponteiros e memória

Ponteiros para função e callbacks em C e C++

Nesta lição, você vai passar uma função como parâmetro para outra função usando ponteiros para função em C e lambdas em C++.

Introdução

Callback é a técnica de passar uma função para outra função, que a chama de volta quando precisar. Assim, um algoritmo genérico pode executar o comportamento escolhido por quem chama sem conhecer os detalhes de implementação. Por exemplo, a mesma função apply pode elevar ao quadrado, dobrar ou fazer qualquer outra transformação.

Pontos importantes

  • Um ponteiro só deve apontar para um objeto que ainda existe, do tipo certo, ou ser nulo.
  • Cada área de memória alocada deve ser liberada exatamente uma vez.
  • Deixe claro qual função é dona da memória (ownership) e quais dados são apenas lidos (const).

Exemplos de código C e C++

C
Executar →
main.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;
}
Resultado da execução
36
C++
Executar →
main.cpp
#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';
}
Resultado da execução
36

Comparação entre C e C++

Em C, o parâmetro int (*operation)(int) é um ponteiro para função que aceita funções com um parâmetro int e retorno int, então apply(6, square) retorna 36. Em C++, lambdas e std::function podem guardar uma variedade maior de objetos chamáveis (callables). Em código que precisa de alto desempenho, templates costumam ser melhores que std::function.

C

A posse e a liberação da memória ficam totalmente por conta do programador.

C++

Contêineres e RAII liberam os recursos automaticamente quando o objeto chega ao fim da vida.

Exercícios práticos

Execute as duas versões e depois mude o código para observar a diferença de segurança que cada linguagem oferece.

  • Teste ponteiros nulos e falhas na alocação de memória.
  • Execute o programa com AddressSanitizer e UndefinedBehaviorSanitizer para encontrar erros de memória.
  • Anote claramente qual ponteiro é dono da memória e qual só serve para leitura.

Pratique com um desafio

Use o conteúdo desta lição para resolver um problema real. Cada desafio roda no navegador, com testes instantâneos e uma revisão por IA.

Todos os desafios