Глава 10. Практические рекомендации #
10.1 Стиль написания кода #
Общие принципы #
- Консистентность - самое важное правило стиля кода
- Читаемость важнее краткости
- Используйте современные соглашения C++
Правила именования #
Переменные:
snake_case
int user_age; std::string first_name;
Классы:
CamelCase
class UserProfile { // ... };
Константы:
UPPER_SNAKE_CASE
const int MAX_BUFFER_SIZE = 1024; constexpr double PI = 3.14159;
Функции:
camelCase
илиsnake_case
void calculateTotalScore(); int get_user_count();
Форматирование кода #
- Отступы - 4 пробела (не Tab)
- Фигурные скобки на новой строке
- Максимальная длина строки - 80-120 символов
- Пробелы вокруг операторов
class Example {
public:
void complexFunction(int param1,
const std::string& param2) {
if (condition) {
// Код с отступом
}
}
};
10.2 Оптимизация производительности #
Общие принципы оптимизации #
- Сначала работоспособность, потом оптимизация
- Измеряй, не предполагай
- Профилируй перед оптимизацией
Методы повышения производительности #
Использование умных указателей
// Вместо raw-указателей std::unique_ptr<Resource> resource = std::make_unique<Resource>();
Передача по константной ссылке
void processData(const std::vector<int>& data) { // Избегаем копирования больших объектов }
Использование move-семантики
std::vector<int> createLargeVector() { std::vector<int> result(1000000); return result; // move-семантика }
Inline-функции для маленьких часто вызываемых функций
inline int square(int x) { return x * x; }
Контейнеры и алгоритмы STL #
- Выбирайте подходящий контейнер
- Используйте алгоритмы STL вместо ручных реализаций
std::vector<int> numbers = {3, 1, 4, 1, 5, 9}; std::sort(numbers.begin(), numbers.end());
10.3 Профилирование #
Инструменты профилирования #
- gprof - классический профайлер GNU
- Valgrind - анализ утечек памяти
- Intel VTune - профилирование производительности
- Chrome Tracing - визуализация производительности
Пример базового профилирования #
#include <chrono>
auto start = std::chrono::high_resolution_clock::now();
// Код, который нужно измерить
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> diff = end - start;
std::cout << "Время выполнения: " << diff.count() << " с" << std::endl;
Рекомендации по профилированию #
- Профилируйте реалистичные сценарии
- Замеряйте полные циклы работы
- Используйте статистическую выборку
- Обращайте внимание на системные вызовы
10.4 Best Practices #
Управление памятью #
- Используйте умные указатели
- Избегайте ручного управления памятью
- RAII (Resource Acquisition Is Initialization)
class ResourceManager {
public:
ResourceManager() {
// Захват ресурса
}
~ResourceManager() {
// Автоматическое освобождение
}
};
Работа с классами #
- Используйте конструкторы по умолчанию
- Реализуйте правило трех/пяти
- Используйте
= default
и= delete
class MyClass {
public:
MyClass() = default; // Конструктор по умолчанию
MyClass(const MyClass&) = delete; // Запрет копирования
};
Многопоточность #
- Используйте высокоуровневые абстракции
std::async
вместо прямой работы с потоками- Минимизируйте shared state
std::future<int> result = std::async(std::launch::async,
[]() {
// Параллельные вычисления
return 42;
});
10.5 Распространенные ошибки и их избежание #
Утечки памяти #
- Всегда используйте умные указатели
- Контролируйте динамическую память
// Плохо
int* ptr = new int[100];
// delete[] ptr; // Можно забыть
// Хорошо
std::unique_ptr<int[]> safe_ptr(new int[100]);
// Автоматическое освобождение
Висячие указатели #
- Обнуляйте указатели после удаления
- Используйте
nullptr
int* ptr = new int(42);
delete ptr;
ptr = nullptr; // Безопасная практика
Undefined Behavior #
- Избегайте выхода за границы массивов
- Проверяйте указатели перед использованием
- Используйте контейнеры STL
std::vector<int> vec = {1, 2, 3};
// vec.at(10); // Безопасная проверка
// vec[10]; // Небезопасно, UB
Заключение #
Следование этим практическим рекомендациям поможет писать более эффективный, безопасный и поддерживаемый код на C++. Помните, что главное - понимание принципов, а не слепое следование правилам.