0Pricing
C++ Academy · Урок

std::function

Храните любые вызываемые объекты

«std::function» — бесплатный урок C++ Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.

Что такое std::function?

std::function — это оболочка со стиранием типа, способная хранить любой вызываемый объект с заданной сигнатурой: свободные функции, лямбды, функторы или связанные выражения.

  • Объявляется с целевой сигнатурой.
  • Определен в <functional>.
#include <iostream>
#include <functional>

int add(int a, int b) { return a + b; }

int main() {
    std::function<int(int, int)> f = add;
    std::cout << f(2, 3) << '\n';
    return 0;
}

Хранение лямбды

В отличие от обычного указателя на функцию, std::function без проблем хранит лямбду, даже если она содержит захваты.

#include <iostream>
#include <functional>

int main() {
    int offset = 10;
    std::function<int(int)> f = [offset](int x) { return x + offset; };
    std::cout << f(5) << '\n';
    return 0;
}

Хранение функтора

Функтор — это объект с operator(). std::function может обернуть его и вызывать его оператор при обращении.

#include <iostream>
#include <functional>

struct Multiplier {
    int factor;
    int operator()(int x) const { return x * factor; }
};

int main() {
    std::function<int(int)> f = Multiplier{3};
    std::cout << f(4) << '\n';
    return 0;
}

Переназначение вызываемого объекта

Одна переменная std::function может указывать на разные вызываемые объекты на протяжении всего времени своего существования, что удобно для замены поведения во время выполнения.

#include <iostream>
#include <functional>

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

Пустой std::function

Созданный конструктором по умолчанию std::function ничего не хранит. Вызов такого объекта выбрасывает исключение std::bad_function_call, поэтому сначала проверьте его.

#include <iostream>
#include <functional>

int main() {
    std::function<void()> f;
    if (f) {
        f();
    } else {
        std::cout << "empty\n";
    }
    return 0;
}

В качестве параметра

Функции могут принимать параметр типа std::function, чтобы работать с любым соответствующим вызываемым объектом, делая интерфейсы гибкими.

#include <iostream>
#include <functional>

void repeat(int n, const std::function<void(int)>& action) {
    for (int i = 0; i < n; ++i) action(i);
}

int main() {
    repeat(3, [](int i) { std::cout << "step " << i << '\n'; });
    return 0;
}

Хранение функций обратного вызова

Один из распространенных вариантов использования — хранить функцию обратного вызова в члене класса, чтобы вызвать её позже, когда произойдет событие.

#include <iostream>
#include <functional>

struct Button {
    std::function<void()> onClick;
    void click() { if (onClick) onClick(); }
};

int main() {
    Button b;
    b.onClick = [] { std::cout << "clicked!\n"; };
    b.click();
    return 0;
}

Вектор вызываемых объектов

Поскольку разные вызываемые объекты имеют один общий тип, их можно хранить вместе в контейнере и вызывать по очереди.

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

int inc(int x) { return x + 1; }

int main() {
    std::vector<std::function<int(int)>> ops;
    ops.push_back(inc);
    ops.push_back([](int x) { return x * 2; });
    for (auto& op : ops) std::cout << op(10) << ' ';
    std::cout << '\n';
    return 0;
}

Цена стирания типа

std::function может выделять память и добавляет косвенный вызов, поэтому работает немного медленнее прямого вызова или вызываемого объекта, заданного шаблоном. Используйте его, когда Вам нужно единообразное хранение.

#include <iostream>
#include <functional>

int main() {
    std::function<int()> f = [] { return 42; };
    int total = 0;
    for (int i = 0; i < 5; ++i) total += f();
    std::cout << total << '\n';
    return 0;
}

Возврат std::function

Фабрика может создать и вернуть настроенный вызываемый объект, позволяя вызывающему коду получать индивидуальное поведение.

#include <iostream>
#include <functional>

std::function<int(int)> adder(int n) {
    return [n](int x) { return x + n; };
}

int main() {
    auto add5 = adder(5);
    std::cout << add5(10) << '\n';
    return 0;
}

Сравнение с указателями на функции

std::function гибче указателя на функцию, поскольку хранит состояние, но за эту гибкость приходится платить небольшой потерей производительности и возможным выделением памяти.

#include <iostream>
#include <functional>

int main() {
    int base = 7;
    std::function<int(int)> stateful = [base](int x) { return x + base; };
    std::cout << "Stateful result: " << stateful(3) << '\n';
    return 0;
}

Быстрая проверка

Проверьте своё понимание std::function.

Повторение

Вы узнали, что std::function:

  • оборачивает любой вызываемый объект, соответствующий его сигнатуре, включая лямбды с состоянием и функторы
  • может переназначаться, храниться в контейнерах и возвращаться фабриками
  • выбрасывает исключение bad_function_call, когда пуст
  • добавляет небольшие накладные расходы из-за стирания типа

Далее Вы воспользуетесь std::bind, чтобы заранее заполнить аргументы вызываемых объектов.

Часто задаваемые вопросы

Урок «std::function» бесплатный?

Да — полный текст урока «std::function» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.

Чему я научусь в уроке «std::function»?

Храните любые вызываемые объекты Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C++ Academy?

Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «std::function»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C++ Academy?

Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Указатели на функции
  2. std::function
  3. std::bind
  4. Выбор вызываемых объектов
← Назад к C++ Academy