Открытый канал ID 76989124909096

C++ geek

Учим C/C++ на примерах

Публикации за период

По реакциям

Поиск и вся лента — после бесплатной регистрации. Свои даты — по подписке; владелец канала видит их бесплатно. Сортировка по реакциям — по подписке. Зарегистрироваться

Загрузка…

🕵️‍♂️ Анатомия лямбд: Что скрывает компилятор и где прячутся тормоза?

Мы привыкли писать auto func = [x](int y) { return x + y; }; и думать о лямбдах как о «магических» встроенных функциях. Но в C++ нет никакой магии. На уровне компилятора лямбд не существует.

Лямбда-выражение - это просто синтаксический сахар для создания анонимного класса (функтора).

⚙️ Что происходит под капотом?

Когда вы пишете такой код:

int multiplier = 10;
auto doMath = [multiplier](int val) {
return val * multiplier;
};

Компилятор молча генерирует для вас класс с уникальным непроизносимым именем и перегруженным оператором ():

// Примерно это генерирует компилятор:
class __Lambda_Uniq_42 {
int multiplier; // Захваченная переменная стала полем класса
public:
__Lambda_Uniq_42(int m) : multiplier(m) {}

// Сам код лямбды:
auto operator()(int val) const {
return val * multiplier;
}
};

// А ваше создание лямбды превращается в:
auto doMath = __Lambda_Uniq_42(multiplier);


Вывод №1: Блок захвата [...] - это просто конструктор класса и его поля. Если вы захватываете по ссылке [&x], полем класса станет ссылка.

🚨 Где прячутся скрытые аллокации?

Сама по себе лямбда создается на стеке. Никаких new или malloc не происходит. Это работает мгновенно.

Тормоза начинаются, когда мы решаем сохранить лямбду с помощью std::function.

// 🚀 БЫСТРО (Zero-cost)
auto fast_lambda = [a, b, c]() { ... };

// 🐢 МОЖЕТ БЫТЬ МЕДЛЕННО (Heap allocation)
std::function<void()> slow_lambda = [a, b, c, d, e]() { ... };

std::function - это тяжелая обертка (Type Erasure). Она должна уметь хранить любой вызываемый объект с нужной сигнатурой.
Чтобы избежать выделения памяти в куче, в std::function встроена оптимизация для маленьких объектов (SBO - Small Buffer Optimization). Размер этого буфера обычно равен размеру нескольких указателей (например, 16-32 байта).

* Если ваша лямбда захватывает мало данных (или ничего) - она поместится во внутренний буфер std::function. Аллокаций нет.
* Если вы написали [=] и захватили кучу тяжелых переменных (или несколько толстых строк/векторов по значению) - размер сгенерированного класса превысит буфер. std::function будет вынужден вызвать new и выделить память в куче.

💡 Правила чистого кода с лямбдами:

1. Храните через auto: Всегда используйте auto для локальных лямбд. Это бесплатно.
2. Передавайте через шаблоны: Если функция принимает лямбду, лучше сделать её шаблоном template <typename Func> void DoWork(Func f), чем принимать std::function. Шаблон сохранит тип лямбды и позволит компилятору заинлайнить код.
3. Используйте std::function только на границах API: Когда вам действительно нужно хранить функции разного типа в одном контейнере (например, вектор коллбеков) или передать их через границу динамической библиотеки.
4. Не пишите [=] вслепую: Захватывайте только то, что реально нужно. Это спасет и от лишних аллокаций, и от случайного копирования тяжелых объектов.

#cpp #lambdas #optimization #memory #under_the_hood #coding #tips

➡️ @channel_cpp_geek
Просмотры: 62
Перейти в пост Открыть в MAX Сообщить о неточности
std::initializer_list

Присваивайте значения контейнерам непосредственно с помощью списка инициализаторов, как это можно делать с C-массивами.

Это справедливо и для вложенных контейнеров. Скажите спасибо С++11.

➡️ @channel_cpp_geek
Просмотры: 195
Перейти в пост Открыть в MAX Сообщить о неточности
🚀 Подборка полезных IT каналов в Max


Системное администрирование, DevOps 📌

https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
https://max.ru/tipsysdmin Типичный Сисадмин
https://max.ru/channel_win_sysadmin Системный Администратор Windows
https://max.ru/channel_linux_admin Linux: Системный администратор
https://max.ru/channel_linuxmod Linux
https://max.ru/channel_i_linux Системный администратор
https://max.ru/channel_devopslib DevOps, SRE, Sysadmin
https://max.ru/channel_devops_star DevOps Star (Звезда Девопса)

Excel лайфхак 📌
https://t.me/Excel_lifehack Excel лайфхак

Английский с нуля 🇬🇧
https://max.ru/UchuEnglish

1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://max.ru/channel_DevLab1C 1С:Предприятие 8

Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
https://max.ru/channel_cpp_geek C++ geek

Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика

Программирование React📌
https://max.ru/react_lib React

Программирование Rust📌
https://max.ru/channel_rust_lib

Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика

Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
https://max.ru/channel_java_geek Java Geek

GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub

Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных

Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков

Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов

Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻

Шутки программистов 📌
https://max.ru/itumor Шутки программистов

Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free

Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров

Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике

Вакансии в IT📌
https://max.ru/progjob
https://max.ru/channel_rabotait

Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных

Городские📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП
https://max.ru/channel_krasnodar_novosty Краснодар Новости
https://max.ru/channel_novosibirsk_novosti Новосибирск
https://max.ru/channel_samara_novosti Новости Самары
https://max.ru/channel_ekaterinburg_novosti Новости Екатеринбурга
https://max.ru/channel_kazan_novosti Новости Казани
https://max.ru/channel_omsk_novosti Новости Омска
https://max.ru/channel_moskva_24 Москва 24
Просмотры: 212
Перейти в пост Открыть в MAX Сообщить о неточности
Что случится, если exception выйдет за пределы потока?

Если exception выходит за пределы потока, то оно не может быть обработано на текущем уровне, т. к. он уже завершен. В таком случае исключение будет зарегистрировано как неперехваченное и может привести к аварийному завершению программы.

Чтобы избежать данной ситуации, необходимо обернуть код, где может возникнуть исключение, в try-catch блок на том же уровне, что и поток, с которым он связан.

➡️ @channel_cpp_geek
Просмотры: 206
Перейти в пост Открыть в MAX Сообщить о неточности
Dependency Injection

Dependency Injection (DI) — это паттерн проектирования, который позволяет управлять зависимостями между объектами. Он помогает разделить создание объектов от их использования и обеспечить более гибкую и тестируемую архитектуру программы.

В DI объекты получают свои зависимости не напрямую, а через внешний источник, который их предоставляет. Этот источник называется контейнером внедрения зависимостей. Контейнер отвечает за создание и управление зависимостями, а объекты получают их через конструкторы, методы или свойства.

➡️ @channel_cpp_geek
Просмотры: 248
Перейти в пост Открыть в MAX Сообщить о неточности
Execution policy для параллельных алгоритмов

Execution policy в C++ — это новшество, введенное в стандарте языка C++17. Это механизм, который позволяет выбрать, как именно должны выполняться алгоритмы в стандартной библиотеке: последовательно или параллельно.

Существуют три варианта execution policy:

- seq: выполняет алгоритм последовательно.
- par: выполняет алгоритм параллельно, используя все доступные ядра процессора.
- par_unseq: выполняет алгоритм параллельно и может использовать неупорядоченное исполнение.

Execution policy может быть использован в комбинации с многими алгоритмами в стандартной библиотеке, такими как std::for_each, std::transform, std::reduce и другими. Например, код выше выполняет алгоритм std::for_each параллельно.

➡️ @channel_cpp_geek
Просмотры: 236
Перейти в пост Открыть в MAX Сообщить о неточности
В чем разница между git fetch и git pull?

Разница между этими командами заключается в том, что когда вы используете команду git fetch, Git извлекает последние изменения из удаленного репозитория в ваш локальный репозиторий, но оставляет эти изменения в отдельной ветке git origin.

А команда git pull извлекает и интегрирует (скачивает и сливает) последние изменения из удаленного репозитория в вашу текущую ветку работы.

➡️ @channel_cpp_geek
Просмотры: 261
Перейти в пост Открыть в MAX Сообщить о неточности
std::tie

std::tie — это функция, которая создает кортеж ссылок на lvalue из своих аргументов или экземпляров std::ignore.

Она может использоваться для распаковки кортежей или пары значений в отдельные переменные. Например, если у вас есть функция, которая возвращает std::pair или std::tuple, вы можете использовать std::tie, чтобы присвоить значения этого кортежа отдельным переменным.

В этом примере мы используем std::tie для распаковки результата вызова set_of_s.insert(value) в две переменные: итератор iter и логическую переменную inserted.
Это позволяет нам проверить, было ли значение успешно вставлено в набор.

➡️ @channel_cpp_geek
Просмотры: 266
Перейти в пост Открыть в MAX Сообщить о неточности
move constructor

Move-конструктор — это специальный конструктор, который позволяет эффективно перемещать ресурсы из одного объекта в другой, без необходимости копирования данных. Он используется для реализации семантики перемещения (move semantics) и оптимизации работы с временными объектами.

Move-конструктор принимает rvalue ссылку (&&) на объект, который будет перемещен, и выполняет простое копирование указателей на данные, а не их фактическое копирование.

Использование move-конструктора позволяет избежать лишних копирований данных и повысить производительность при работе с большими или ресурсоемкими объектами.

➡️ @channel_cpp_geek
Просмотры: 262
Перейти в пост Открыть в MAX Сообщить о неточности
Move-only объекты и почему std::unique_ptr нельзя копировать

Многие удивляются, когда компилятор ругается: «unique_ptr не имеет конструктора копирования». Это не баг, а фича: он move-only. Логика простая: владелец ресурса должен быть только один.

#include <memory>
#include <iostream>

int main() {
std::unique_ptr<int> p1 = std::make_unique<int>(42);

// std::unique_ptr<int> p2 = p1; // ❌ ошибка копирования

std::unique_ptr<int> p2 = std::move(p1); // ✅ перенос
std::cout << *p2 << "\n"; // 42
std::cout << (p1 ? "not null" : "null") << "\n"; // null
}


Ключевой момент: после std::move старый указатель «обнуляется», чтобы избежать двойного освобождения памяти.

Если нужен shareable ресурс – используйте std::shared_ptr. Но помните: это дороже (счётчик ссылок, атомики).

Частая ошибка на собеседованиях: «почему нельзя вернуть unique_ptr по значению?» - на самом деле можно! Он спокойно двигается:

std::unique_ptr<int> make_ptr() {
return std::make_unique<int>(99); // move происходит неявно
}

👉 Правило: если объект владеет чем-то уникально – делайте его move-only (удалите копирование). Это повышает безопасность кода и явно выражает семантику владения.

➡️ @channel_cpp_geek
Просмотры: 238
Перейти в пост Открыть в MAX Сообщить о неточности
Вся лента — после бесплатной регистрации
ВКонтакте Телеграм Одноклассники
Избранное в datool.ru

Следите за каналом в личном кабинете

Зарегистрируйтесь в datool.ru, чтобы добавить канал «C++ geek» в избранное и отслеживать его показатели.

Зарегистрироваться
Для владельцев каналов

Подтвердите свой канал

Войдите или зарегистрируйтесь в datool.ru, затем добавьте нашего бота в канал по инструкции в личном кабинете. После проверки владения замок исчезнет и вам станет доступно управление каналом.

Войти или зарегистрироваться

Сообщить о неточности

Опишите, что нужно исправить. Если есть источник, добавьте ссылку.

Вы покидаете datool.ru

Ссылка ведёт на внешний сайт. datool.ru не отвечает за его содержимое — проверьте адрес, прежде чем вводить пароли или платёжные данные.

Переход через 10 с

Перейти