Практические рекомендации

Глава 10. Практические рекомендации #

10.1 Стиль написания кода #

Общие принципы #

  1. Консистентность - самое важное правило стиля кода
  2. Читаемость важнее краткости
  3. Используйте современные соглашения 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 Оптимизация производительности #

Общие принципы оптимизации #

  1. Сначала работоспособность, потом оптимизация
  2. Измеряй, не предполагай
  3. Профилируй перед оптимизацией

Методы повышения производительности #

  • Использование умных указателей

    // Вместо 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;

Рекомендации по профилированию #

  1. Профилируйте реалистичные сценарии
  2. Замеряйте полные циклы работы
  3. Используйте статистическую выборку
  4. Обращайте внимание на системные вызовы

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++. Помните, что главное - понимание принципов, а не слепое следование правилам.