Глава 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++.