Senior C++ Developer
12.9K subscribers
1.29K photos
3 videos
587 links
№ 4931128893
Изучаем C++.

По вопросам сотрудничества: @adv_and_pr
Download Telegram
➡️ Универсальные ссылки

В официальной терминологии известные как forwarding references (передаваемые ссылки). Универсальная ссылка объявляется с помощью синтаксиса Т&&, где Т является шаблонным параметром типа, или с помощью auto&&. Они в свою очередь служат фундаментом для двух других крупных фич:

move-семантика
И perfect forwarding, возможность передавать аргументы, которые являются либо lvalue, либо rvalue.

Универсальные ссылки позволяют ссылаться на привязку либо к lvalue, либо к rvalue в зависимости от типа. Универсальные ссылки следуют правилам свертывания ссылок:

1. T& & становится T&
2. T& && становится T&
3. T&& & становится T&
4. T&& && становится T&&
Please open Telegram to view this post
VIEW IN TELEGRAM
➡️ Удаленные и дефолтные функции

struct demo
{
demo() = default;
};

demo d;


У вас вполне закономерно может возникнуть вопрос, зачем вам писать 8+ букв (т.е. = default;), когда можно просто использовать {}, т.е. пустой конструктор? Никто вас не останавливает. Но подумай о конструкторе копирования, операторе копирования присваиванием, и т.д.

Пустой конструктор копирования, например, не то же самое, что конструктор копирования по умолчанию (который будет выполнять почленную копию всех членов).

Вы можете ограничить определенную операцию или способ инстанцирования объекта, просто удалив соответствующий метод, как показано ниже:

class demo
{
int m_x;

public:
demo(int x) : m_x(x){};
demo(const demo &) = delete;
demo &operator=(const demo &) = delete;
};

demo obj1{123};
demo obj2 = obj1; // ОШИБКА -- вызов удаленного конструктора копирования
obj2 = obj1; // ОШИБКА -- оператор = удален


🗣️ В старом С++ вы должны были сделать его приватным. Но теперь в вашем распоряжении есть директива компилятора delete.
Please open Telegram to view this post
VIEW IN TELEGRAM
➡️ Делегирование конструкторов

В старом C++ вам нужно создавать функцию-член для инициализации и вызывать ее из всех конструкторов для достижения универсально инициализации.

Но начиная с C++11 конструкторы теперь могут вызывать другие конструкторы из того же класса с помощью списка инициализаторов.
Please open Telegram to view this post
VIEW IN TELEGRAM
➡️ Диапазоны и итераторы в C++

В C++ стандартная библиотека шаблонов (STL) предоставляет мощные инструменты для работы с коллекциями данных.

Диапазоны и итераторы позволяют вам легко и эффективно перебирать элементы контейнеров, таких как векторы, списки и множества.

Использование диапазонов и итераторов делает код более чистым и читаемым, упрощает операции перебора и модификации элементов контейнеров.
Please open Telegram to view this post
VIEW IN TELEGRAM
➡️ Концепты (Concepts) в C++

Концепты - это новая возможность в C++20, которая позволяет задавать ограничения на шаблонные параметры. Это позволяет писать более безопасный и читаемый код, поскольку компилятор проверяет соответствие типов требованиям концептов на этапе компиляции.

• template<typename T> concept Arithmetic = std::is_arithmetic_v<T>; определяет концепт Arithmetic, который ограничивает типы, для которых значение std::is_arithmetic_v<T> истинно (т.е. типы, которые являются арифметическими).

• template<Arithmetic T> T add(const T& a, const T& b) определяет шаблонную функцию add, которая будет компилироваться только для типов, удовлетворяющих концепту Arithmetic.
Использование функции add:

Примеры с целыми числами и числами с плавающей запятой успешно вызывают функцию add.

Пример со строками (закомментированный) вызовет ошибку компиляции, так как std::string не является арифметическим типом.
Please open Telegram to view this post
VIEW IN TELEGRAM
➡️ Модули (Modules) в C++

Модули - это система сборки и организации кода, представленная в C++20.

Они улучшают компиляцию и организацию кода, предоставляя более четкий и эффективный способ управления зависимостями.

Модули заменяют использование препроцессорных директив #include, улучшая время компиляции и предотвращая проблемы с зависимостями и макросами.

Модули значительно сокращают время компиляции по сравнению с традиционными заголовочными файлами, так как они компилируются только один раз.

Модули предотвращают проблемы, связанные с макросами и конфликтами имен, поскольку они предоставляют четкие границы и изолированные области видимости.

Модули упрощают управление зависимостями и организацию кода, что делает проекты более поддерживаемыми и масштабируемыми.
Please open Telegram to view this post
VIEW IN TELEGRAM
➡️ auto & decltype

auto-типизированные переменные выводятся компилятором на основе типа их инициализатора.
Чрезвычайно полезно с точки зрения удобочитаемости, особенно для сложных типов:

// std::vector<int>::const_iterator cit = v.cbegin();
auto cit = v.cbegin(); // альтернатива

// std::shared_ptr<vector<uint32_t>> demo_ptr(new vector<uint32_t>(0);
auto demo_ptr = make_shared<vector<uint32_t>>(0); // альтернатива


Функции также могут выводить тип возвращаемого значения с помощью auto. В C++11 тип возвращаемого значения должен быть указан либо явно, либо с помощью decltype, например:

template <typename X, typename Y>
auto add(X x, Y y) -> decltype(x + y)
{
return x + y;
}
add(1, 2); // == 3
add(1, 2.0); // == 3.0
add(1.5, 1.5); // == 3.0


Приведенная выше форма определения возвращаемого типа называется trailing return type, т.е. -> return-type.
Please open Telegram to view this post
VIEW IN TELEGRAM
Snakeискусственный интеллект для игры «Змейка»

Цель змеи – постоянно есть пищу и как можно скорее заполнить карту своим телом

Первоначально проект был написан на C++. Теперь он был переписан на Python с удобным графическим интерфейсом для пользователя

https://github.com/chuyangliu/snake
#вопросы_с_собоседований
В чем различия между delete и delete[]?

delete предназначен для уничтожения объектов, память под которые выделена при помощи new(). delete[] для объектов выделенных при помощи оператора new[]().

При неправильном использовании оператора delete (например, delete вместо delete[]) результат будет: undefined behavior.
#вопросы_с_собеседований
В чем проблема следующего фрагмента?

Из спецификации (C++11 §5.3.5/3):

Если статический тип подлежащего удалению объекта отличается от его динамического типа, статический тип должен быть базовым классом динамического типа подлежащего удалению объекта и иметь виртуальный деструктор или поведение undefined.
Преобразование вектора в массив

Для этого есть довольно простой трюк, поскольку спецификация теперь гарантирует, что векторы хранят свои элементы последовательно.
Что нужно дописать, чтобы при вызове конструктора перемещения член класса действительно "переместился"?

Нужно дописать std::move в списке инициализации перемещающего конструктора:
A(A&& oth) : str(std::move(oth.str)){ }

Но это гарантирует "перемещение" только в том случае, если у этого объекта, в свою очередь, есть перемещающий конструктор (в данном случае, у std::string он есть).
Алгоритм prev_permutation

Алгоритм переставляет элементы так, чтобы получилась предыдущая в лексикографическом порядке перестановка. Можно применять не только к векторам, но и к строкам (как и многие другие алгоритмы).

Метод возвращает true, если удалось построить предыдущую в лексикографическом порядке перестановку. Если же первоначальная перестановка уже была минимальной в лексикографическом порядке, то метод генерирует максимальную в лексикографическом порядке перестановку и возвращает false.
Как сравнивают bool, int, float, указатели со значением и с нулем?

Ответ на картинке.
FFmpeg libav с нуля. Часть 1: знакомство и начало работы

FFmpeg - это набор библиотек и утилит командной строки, которые используются повсеместно для обработки мультимедийных материалов.

Смотреть статью
Указатели, ссылки и массивы в C и C++: точки над i

Смотреть статью
Перегрузка в C++. Часть I. Перегрузка функций и шаблонов

Смотреть статью
Основные концепции библиотеки chrono (C++)

Работа со временем как с безразмерной величиной может приводить к недоразумениям и ошибкам конвертации временных единиц измерения.

Для избежания таких ошибок предусмотрена библиотека chrono (namespace std::chrono). Она была добавлена в C++11 и дорабатывалась в поздних стандартах.

Смотреть статью
Что нам не нравится в C++

Смотреть статью