Как включить все стандартные библиотеки одной командой
Чтобы разом включить в проект все стандартные библиотеки, используйте #include <bits/stdc++.h>. Это особенно полезно в условиях дефицита времени на соревнованиях по программированию.
Но помните, что:
#include <bits/stdc++.h>
содержит множество заголовочных файлов, которые, возможно, и не понадобятся в конкретном проекте. А это может привести к увеличению времени компиляции.
#include <bits/stdc++.h> не является стандартным заголовочным файлом библиотеки GNU C++. Таким образом, не относящиеся к типу GCC (GNU Compiler Collection) компиляторы могут испытывать затруднения в процессе исполнения. Однако так бывает не часто!
➡️ @cpp_geek
Чтобы разом включить в проект все стандартные библиотеки, используйте #include <bits/stdc++.h>. Это особенно полезно в условиях дефицита времени на соревнованиях по программированию.
Но помните, что:
#include <bits/stdc++.h>
содержит множество заголовочных файлов, которые, возможно, и не понадобятся в конкретном проекте. А это может привести к увеличению времени компиляции.
#include <bits/stdc++.h> не является стандартным заголовочным файлом библиотеки GNU C++. Таким образом, не относящиеся к типу GCC (GNU Compiler Collection) компиляторы могут испытывать затруднения в процессе исполнения. Однако так бывает не часто!
➡️ @cpp_geek
Как включить все стандартные библиотеки одной командой
Чтобы разом включить в проект все стандартные библиотеки, используйте #include <bits/stdc++.h>. Это особенно полезно в условиях дефицита времени на соревнованиях по программированию.
Но помните, что:
#include <bits/stdc++.h>
содержит множество заголовочных файлов, которые, возможно, и не понадобятся в конкретном проекте. А это может привести к увеличению времени компиляции.
#include <bits/stdc++.h> не является стандартным заголовочным файлом библиотеки GNU C++. Таким образом, не относящиеся к типу GCC (GNU Compiler Collection) компиляторы могут испытывать затруднения в процессе исполнения. Однако так бывает не часто!
➡️ @cpp_geek
Чтобы разом включить в проект все стандартные библиотеки, используйте #include <bits/stdc++.h>. Это особенно полезно в условиях дефицита времени на соревнованиях по программированию.
Но помните, что:
#include <bits/stdc++.h>
содержит множество заголовочных файлов, которые, возможно, и не понадобятся в конкретном проекте. А это может привести к увеличению времени компиляции.
#include <bits/stdc++.h> не является стандартным заголовочным файлом библиотеки GNU C++. Таким образом, не относящиеся к типу GCC (GNU Compiler Collection) компиляторы могут испытывать затруднения в процессе исполнения. Однако так бывает не часто!
➡️ @cpp_geek
👍5
📌 Оптимизация кода с
Привет, друзья! Сегодня поговорим про
💡 Зачем нужен
Обычно, если функция не может вернуть корректное значение, приходится использовать:
✔ Возвращаемое значение с ошибочным кодом (неудобно, особенно если 0 или
✔ Выброс исключения (дорого по ресурсам).
✔ Указатели (
🔥 Альтернатива? Используем
✅ Код стал чище: нет лишних проверок
🎯 Когда использовать?
🔹 Когда функция может вернуть "ничего", но исключения и специальные значения не подходят.
🔹 Для более понятного API (например, парсинг строки в число).
🔹 Когда важно избежать неопределенного состояния (например, с переменной внутри класса).
А ты уже используешь
➡️ @cpp_geek
std::optional
в C++ Привет, друзья! Сегодня поговорим про
std::optional
— мощный инструмент, который делает код чище и безопаснее. 💡 Зачем нужен
std::optional
? Обычно, если функция не может вернуть корректное значение, приходится использовать:
✔ Возвращаемое значение с ошибочным кодом (неудобно, особенно если 0 или
-1
могут быть валидными). ✔ Выброс исключения (дорого по ресурсам).
✔ Указатели (
nullptr
, но требует дополнительных проверок). 🔥 Альтернатива? Используем
std::optional
!
#include <iostream>
#include <optional>
#include <string>
std::optional<std::string> findUser(int id) {
if (id == 42) return "John Doe";
return std::nullopt;
}
int main() {
auto user = findUser(42);
if (user) {
std::cout << "User found: " << *user << std::endl;
} else {
std::cout << "User not found!" << std::endl;
}
}
✅ Код стал чище: нет лишних проверок
nullptr
, исключений или специальных значений. 🎯 Когда использовать?
🔹 Когда функция может вернуть "ничего", но исключения и специальные значения не подходят.
🔹 Для более понятного API (например, парсинг строки в число).
🔹 Когда важно избежать неопределенного состояния (например, с переменной внутри класса).
А ты уже используешь
std::optional
в своем коде? Делись опытом в комментариях! ⬇🔍➡️ @cpp_geek
👍17
⚡
Сегодня поговорим о
❌ Проблема: Лишние копии данных
Представьте, что у нас есть функция, принимающая массив чисел:
С одной стороны, передача
Придётся перегружать функцию или копировать данные в
✅ Решение: Используем
🚀 Преимущества
✅ Не копирует данные — передаётся как ссылка
✅ Работает с любыми последовательностями
✅ Гибкость — можно создавать срезы без копий
Пример использования
⚠️ Важно
-
- Не поддерживает автоматическое изменение размера, как
📌 Итог
Если ваша функция принимает
➡️ @cpp_geek
std::span
— мощная альтернатива std::vector
и std::array
Сегодня поговорим о
std::span
— контейнере, который делает работу с массивами и векторами в C++ более удобной и эффективной. 🚀 ❌ Проблема: Лишние копии данных
Представьте, что у нас есть функция, принимающая массив чисел:
void processArray(const std::vector<int>& arr) {
for (int num : arr) {
std::cout << num << " ";
}
std::cout << std::endl;
}
С одной стороны, передача
const std::vector<int>&
предотвращает копирование, но что, если у нас массив std::array
или сырой int[]
? Придётся перегружать функцию или копировать данные в
std::vector
. ✅ Решение: Используем
std::span
std::span
позволяет передавать любой диапазон (`std::vector`, std::array
, сырые массивы) без копирования:
#include <iostream>
#include <span>
#include <vector>
#include <array>
void processArray(std::span<int> arr) {
for (int num : arr) {
std::cout << num << " ";
}
std::cout << std::endl;
}
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::array<int, 5> arr = {6, 7, 8, 9, 10};
int rawArr[] = {11, 12, 13, 14, 15};
processArray(vec); // ✅ Работает
processArray(arr); // ✅ Работает
processArray(rawArr); // ✅ Работает
}
🚀 Преимущества
std::span
✅ Не копирует данные — передаётся как ссылка
✅ Работает с любыми последовательностями
✅ Гибкость — можно создавать срезы без копий
Пример использования
.subspan()
, чтобы передавать часть массива:
std::vector<int> vec = {1, 2, 3, 4, 5};
std::span<int> sp = vec;
processArray(sp.subspan(2)); // Выведет: 3 4 5
⚠️ Важно
-
std::span
не владеет данными. Убедитесь, что исходные данные живут дольше span
. - Не поддерживает автоматическое изменение размера, как
std::vector
. 📌 Итог
Если ваша функция принимает
std::vector<int>&
, std::array<int, N>&
, int[]
или даже std::initializer_list<int>
, замените их на std::span<int>
! Это сделает код более гибким и эффективным. 🔥 ➡️ @cpp_geek
👍20❤2🔥1
Как упростить дебаг через
Когда вы отлаживаете сложный баг, бывает сложно быстро понять, где и почему произошла ошибка. С C++20 стало гораздо проще автоматизировать логирование и сделать его по-настоящему информативным.
Вот пример:
📌 Этот код выведет:
Вы больше не пишете руками
➡️ @cpp_geek
std::format
и std::source_location
Когда вы отлаживаете сложный баг, бывает сложно быстро понять, где и почему произошла ошибка. С C++20 стало гораздо проще автоматизировать логирование и сделать его по-настоящему информативным.
Вот пример:
#include <iostream>
#include <format>
#include <source_location>
void log(const std::string& message,
const std::source_location location = std::source_location::current())
{
std::cout << std::format("[{}:{} - {}] {}\n",
location.file_name(),
location.line(),
location.function_name(),
message);
}
int divide(int a, int b)
{
if (b == 0) {
log("Попытка деления на ноль");
return 0;
}
return a / b;
}
📌 Этот код выведет:
[main.cpp:16 - divide] Попытка деления на ноль
Вы больше не пишете руками
__FILE__
, __LINE__
и __func__
. Всё это делает std::source_location
. А с std::format
— красиво и читаемо.➡️ @cpp_geek
👍13❤3🔥1
🧵 RAII — главный секрет устойчивого к утечкам C++ кода
Привет! Сегодня хочу напомнить о технике, без которой невозможно писать безопасный и устойчивый C++ код — это RAII (Resource Acquisition Is Initialization).
RAII — это идиома, в которой захват ресурса (файл, сокет, память, мьютекс) происходит в конструкторе объекта, а освобождение — в деструкторе. Благодаря этому ресурсы освобождаются автоматически, даже при исключениях.
Пример:
RAII делает твой код:
✅ Безопасным к утечкам
✅ Устойчивым к исключениям
✅ Лёгким для чтения и сопровождения
💡 Совет: всегда оборачивай "ручные" ресурсы в обёртки —
➡️ @cpp_geek
Привет! Сегодня хочу напомнить о технике, без которой невозможно писать безопасный и устойчивый C++ код — это RAII (Resource Acquisition Is Initialization).
RAII — это идиома, в которой захват ресурса (файл, сокет, память, мьютекс) происходит в конструкторе объекта, а освобождение — в деструкторе. Благодаря этому ресурсы освобождаются автоматически, даже при исключениях.
Пример:
#include <fstream>
void saveData(const std::string& filename) {
std::ofstream file(filename); // открытие файла
if (!file.is_open())
throw std::runtime_error("Cannot open file");
file << "some data"; // файл закроется автоматически
}
RAII делает твой код:
✅ Безопасным к утечкам
✅ Устойчивым к исключениям
✅ Лёгким для чтения и сопровождения
💡 Совет: всегда оборачивай "ручные" ресурсы в обёртки —
std::unique_ptr
, std::lock_guard
, std::ofstream
, std::thread
и т.д.➡️ @cpp_geek
👍14❤1💯1
🔥 Ловим баги в 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
👍7❤1
🚀 Сегодня я покажу вам простой, но очень полезный приём в 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
👍8🔥5🥱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
👍20
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
👍7👎1