Современные возможности

Глава 7. Современные возможности C++ #

1. Auto и Decltype #

1.1 Ключевое слово auto #

Ключевое слово auto позволяет компилятору автоматически выводить тип переменной:

auto x = 42;           // x будет int
auto pi = 3.14159;     // pi будет double
auto str = "Привет";   // str будет const char*

// Работа с контейнерами
std::vector<int> numbers = {1, 2, 3, 4, 5};
for (auto num : numbers) {
    std::cout << num << " ";  // Автоматический вывод типа в цикле
}

1.2 Decltype #

decltype позволяет получить тип выражения во время компиляции:

int x = 10;
decltype(x) y = 20;    // y будет типа int

// Использование с шаблонами
template <typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
    return t + u;
}

// Автовыведение типа возвращаемого значения
auto result = add(5, 3.14);  // Результат будет double

2. Ссылки R-value #

2.1 Основы R-value ссылок #

R-value ссылки позволяют более эффективно работать с временными объектами:

// R-value ссылка
void processValue(int&& val) {
    std::cout << "R-value ссылка: " << val << std::endl;
}

int getValue() {
    return 42;
}

int main() {
    int x = 10;
    // processValue(x);   // Ошибка! x - lvalue
    processValue(42);      // OK, передача r-value
    processValue(getValue());  // OK, передача временного объекта
}

2.2 Семантика перемещения #

class ResourceManager {
    std::string data;
public:
    // Конструктор перемещения
    ResourceManager(ResourceManager&& other) noexcept 
        : data(std::move(other.data)) {
        // Эффективное перемещение ресурсов
    }
};

3. Perfect Forwarding #

Perfect forwarding позволяет передавать аргументы с сохранением их категории value:

template<typename T, typename... Args>
std::unique_ptr<T> makeUnique(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

// Пример использования
struct Complex {
    Complex(int x, double y) {}
};

auto obj = makeUnique<Complex>(10, 3.14);

4. Constexpr #

Constexpr позволяет вычислять значения во время компиляции:

// Функция, вычисляемая во время компиляции
constexpr int factorial(int n) {
    return (n <= 1) ? 1 : (n * factorial(n - 1));
}

// Компилируется во время компиляции
constexpr int result = factorial(5);  // result будет 120

// Constexpr конструкторы
class Point {
    int x, y;
public:
    constexpr Point(int x, int y) : x(x), y(y) {}
    
    constexpr int getX() const { return x; }
    constexpr int getY() const { return y; }
};

constexpr Point p(10, 20);
static_assert(p.getX() == 10, "Компиляция во время выполнения");

5. Variadic Templates #

Шаблоны с переменным числом аргументов:

// Базовый случай для рекурсии
void print() {
    std::cout << std::endl;
}

// Шаблонная функция с variadic параметрами
template<typename T, typename... Args>
void print(T first, Args... args) {
    std::cout << first << " ";
    print(args...);  // Рекурсивный вызов
}

int main() {
    print(1, 2.5, "Привет");  // Можно передавать разные типы
}

// Fold-выражения (С++17)
template<typename... Args>
auto sum(Args... args) {
    return (args + ...);  // Суммирование всех аргументов
}

int total = sum(1, 2, 3, 4, 5);  // total будет 15

6. Delegating Constructors #

Делегирующие конструкторы позволяют одному конструктору вызывать другой:

class Person {
    std::string name;
    int age;

public:
    // Основной конструктор
    Person(std::string n, int a) : name(n), age(a) {}

    // Делегирующий конструктор
    Person() : Person("Неизвестно", 0) {}
    Person(std::string n) : Person(n, 0) {}
};

7. Наследование конструкторов #

class Base {
public:
    Base(int x) {}
    Base(std::string s) {}
};

class Derived : public Base {
public:
    // Наследование конструкторов базового класса
    using Base::Base;

    // Можно добавить свои собственные конструкторы
    Derived(double d) : Base(static_cast<int>(d)) {}
};

Заключение #

Современные возможности C++ существенно упрощают разработку, делая код более выразительным и эффективным:

  • auto и decltype упрощают работу с типами
  • R-value ссылки оптимизируют управление ресурсами
  • Variadic templates позволяют создавать более гибкие шаблонные функции
  • constexpr дает возможность выполнять вычисления во время компиляции
  • Делегирующие конструкторы и наследование конструкторов упрощают создание классов

Ключевые моменты:

  • Автоматический вывод типов
  • Эффективное управление памятью
  • Шаблоны с переменным числом параметров
  • Компиляционные вычисления
  • Гибкость при создании классов

Изучение этих возможностей позволит писать более современный и эффективный код на C++.