0Pricing
C++ Academy · Aula

Escolha de objetos chamáveis

Lambdas versus bind versus ponteiros

Escolha de objetos chamáveis é uma aula grátis de C++ Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C++ Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C++ Academy inclui 4 aulas no total.

A caixa de ferramentas de objetos chamáveis

O C++ oferece várias formas de passar comportamento: ponteiros de função, lambdas, functores, std::bind e std::function. Cada uma atende a necessidades diferentes.

  • Velocidade versus flexibilidade é o compromisso mais comum.
  • A legibilidade também é 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 usar um ponteiro de função

Escolha um ponteiro de função quando precisar de uma pequena função de retorno sem estado e quiser compatibilidade com C ou sobrecarga zero.

#include <iostream>

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

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

Quando usar uma lambda

Uma lambda é a escolha padrão moderna: é concisa, pode capturar estado e o compilador a incorpora bem em modelos e algoritmos.

#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;
}

Capturando estado em uma lambda

As lambdas capturam variáveis do contexto ao redor, algo que os ponteiros de função não podem fazer, o que as torna ideais para funções de retorno sensíveis ao contexto.

#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 usar um functor

Um functor (uma estrutura com operator()) é adequado para uma operação nomeada e reutilizável que pode armazenar configurações e ser usada em vários lugares.

#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 versus bind

Ambos podem preencher argumentos previamente. A versão com lambda geralmente é mais clara e mais fácil de otimizar para o compilador, portanto prefira-a 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 usar std::function

Use std::function quando precisar armazenar um objeto chamável cujo tipo concreto seja desconhecido, por exemplo, em um membro de classe ou em um contêiner.

#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;
}

Modelos evitam sobrecarga

Se uma função só precisar receber um objeto chamável, sem armazená-lo, um parâmetro de modelo manterá a velocidade máxima ao evitar o apagamento de tipo.

#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ção de desempenho

De forma aproximada: um objeto chamável baseado em modelo ou uma lambda sem captura é mais rápido, um ponteiro de função vem logo depois e std::function é o mais lento devido à indireção e à possível alocação.

#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;
}

Um guia para decidir

Guia rápido:

  • Precisa armazenar qualquer objeto chamável? std::function.
  • Apenas receber um objeto chamável em uma função genérica? Parâmetro de modelo.
  • Comportamento embutido com estado? lambda.
  • API de C ou sem estado? ponteiro de função.
#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;
}

Reunindo tudo

Um pequeno sistema de eventos pode receber manipuladores de forma genérica, mas armazená-los em std::function para que possam ser invocados mais tarde.

#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ção rápida

Teste a sua compreensão sobre como escolher objetos chamáveis.

Recapitulação

Você aprendeu a escolher um objeto chamável:

  • ponteiro de função para funções de retorno sem estado e compatíveis com C
  • lambda como escolha padrão para comportamento embutido com estado
  • functor para operações nomeadas e reutilizáveis
  • parâmetro de modelo quando você só recebe um objeto chamável (mais rápido)
  • std::function quando precisa armazenar um objeto de tipo desconhecido

Isso conclui o curso de Objetos de Função e std::bind.

Perguntas Frequentes

A aula “Escolha de objetos chamáveis” é grátis?

Sim — o texto completo de “Escolha de objetos chamáveis” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C++ Academy, atualize para CoddyKit PRO. O curso de C++ Academy inclui 4 aulas no total.

O que vou aprender em “Escolha de objetos chamáveis”?

Lambdas versus bind versus ponteiros Você pratica C++ Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar C++ Academy?

Nenhuma experiência prévia é necessária. C++ Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Escolha de objetos chamáveis”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de C++ Academy?

Sim. Cada aula de C++ Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Ponteiros para funções
  2. std::function
  3. std::bind
  4. Escolha de objetos chamáveis
← Voltar para C++ Academy