13626
Изучаем C++. По вопросам сотрудничества: @adv_and_pr
➡️ Lambda-функции и их использование
Lambda-функции — это мощный инструмент в C++, позволяющий определять анонимные функции прямо в месте их использования.• Они особенно полезны для создания компактного и читаемого кода, например, при работе с алгоритмами из стандартной библиотеки (STL).
➡️ Наследование с помощью private и public• Использование private и public при наследовании в C++ позволяет контролировать доступ к членам базового класса в производных классах.• Это может быть полезно для сокрытия частей реализации базового класса от внешнего мира или ограничения доступа к членам в иерархии классов.• Эта фишка особенно полезна при проектировании классов и их взаимодействия, позволяя более гибко управлять доступом к данным и методам в рамках наследования.
➡️ Функции в качестве параметра шаблона• Параметром шаблона могут быть конкретные целые числа.• Параметром шаблона также могут быть конкретные функции.• Это позволяет компилятору встраивать вызовы для этих функций в коде инстанцированного шаблона для более эффективного выполнения.• В примере ниже, функция memoize() в качестве шаблонного параметра получает функцию и вызывает эту функцию для новых значений аргумента.• Старое сохранённое значение аргумента берётся из кеша.
➡️ Использование SFINAE для селективной компиляции функций
SFINAE (Substitution Failure Is Not An Error) — это одна из самых мощных и менее известных техник в C++, которая позволяет выбирать, какие функции должны быть скомпилированы, на основе доступности определенных типов или выражений.• SFINAE позволяет автоматически исключать функции из компиляции, если параметры или выражения не соответствуют определенным условиям. Это достигается с помощью специальных инструментов, таких как std::enable_if.• В примере выше используются std::enable_if_t и std::is_integral_v для выбора функции, которая будет скомпилирована, на основе типа передаваемого аргумента.• SFINAE делает код более универсальным и позволяет использовать единую функцию для обработки различных типов данных, выбирая правильную реализацию на этапе компиляции.
➡️ Приведение типов• Приведение в стиле C изменяет только тип, не затрагивая сами данные. В то время как старый C++ имел небольшой уклон в типобезопасность, он предоставлял фичу указания оператора/функции преобразования типа.• Но это было неявное преобразование типов. Начиная с C++11, функции преобразования типов теперь можно сделать явными с помощью спецификатора explicit следующим образом:
struct demoЧитать полностью…
{
explicit operator bool() const { return true; }
};
demo d;
if (d); // OK, вызывает demo::operator bool()
bool b_d = d; // ОШИБКА: не может преобразовать 'demo' в 'bool' во время инициализации
bool b_d = static_cast<bool>(d); // OK, явное преобразование, вы знаете, что делаете
➡️ Циклы for по диапазону• Синтаксический сахар для перебора элементов контейнера.
std::array<int, 5> a {1, 2, 3, 4, 5};
for (int& x : a) x *= 2;
// a == { 2, 4, 6, 8, 10 }
• Обратите внимание на разницу при использовании int в противовес int&:std::array<int, 5> a {1, 2, 3, 4, 5};
for (int x : a) x *= 2;
// a == { 1, 2, 3, 4, 5 }
Читать полностью…
➡️ Удаленные и дефолтные функции
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; // ОШИБКА -- оператор = удален
➡️ Делегирование конструкторов• В старом C++ вам нужно создавать функцию-член для инициализации и вызывать ее из всех конструкторов для достижения универсально инициализации.• Но начиная с C++11 конструкторы теперь могут вызывать другие конструкторы из того же класса с помощью списка инициализаторов.
➡️ Концепты (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 не является арифметическим типом.
➡️ 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.
Читать полностью…
#вопросы_с_собоседований
В чем различия между delete и delete[]?
delete предназначен для уничтожения объектов, память под которые выделена при помощи new(). delete[] для объектов выделенных при помощи оператора new[]().
При неправильном использовании оператора delete (например, delete вместо delete[]) результат будет: undefined behavior.
Алгоритм prev_permutation
Алгоритм переставляет элементы так, чтобы получилась предыдущая в лексикографическом порядке перестановка. Можно применять не только к векторам, но и к строкам (как и многие другие алгоритмы).
Метод возвращает true, если удалось построить предыдущую в лексикографическом порядке перестановку. Если же первоначальная перестановка уже была минимальной в лексикографическом порядке, то метод генерирует максимальную в лексикографическом порядке перестановку и возвращает false.
С++26 и рефлексия: что нового и как это изменит программирование?
🚀На последней встрече ISO C++ в Софии обсудили долгожданные новшества в стандарте С++26, и они реально впечатляют. Одно из самых ожидаемых нововведений — рефлексия на уровне компиляции. Это значит, что теперь можно будет работать с типами и метаданными прямо в коде, без жертвования производительностью.
Но это не всё: новые возможности для параллельных алгоритмов, улучшенная безопасность и ещё множество фишек, которые точно изменят представление о C++. Городские сервисы Яндекса собрали и структурировали всё самое важное со встречи. Такое мы читаем!
Реклама. ООО «ЯНДЕКС», ИНН 7736207543
➡️ Сжатие данных с использованием std::vector::shrink_to_fitstd::vector::shrink_to_fit — метод, который позволяет уменьшить емкость вектора до его фактического размера. Это полезно, когда нужно освободить память, занимаемую неиспользуемыми элементами, особенно после значительного сокращения размера вектора.• Вектор заполняется 100 элементами, после чего большая часть элементов удаляется. Использование shrink_to_fit позволяет уменьшить емкость вектора до текущего количества элементов, что освобождает ненужную память.• Используйте shrink_to_fit, когда нужно минимизировать использование памяти после удаления большого числа элементов из вектора. Это улучшает производительность и снижает потребление ресурсов, что особенно важно в средах с ограниченной памятью.
➡️ Оптимизация доступа к элементам через std::deque с использованием индексацииstd::deque — это контейнер, который позволяет эффективное добавление и удаление элементов как с начала, так и с конца. В отличие от std::vector, std::deque обеспечивает постоянное время доступа к элементам как в начале, так и в конце контейнера.• Используйте std::deque в тех случаях, когда вам нужен быстрый доступ к элементам по индексу, но также важна возможность эффективного добавления и удаления элементов с обоих концов контейнера.
➡️ Строго типизированные перечисления• Типобезопасные перечисления, которые решают множество проблем с C-перечислениями, включая неявные преобразования, арифметические операции, невозможность указать базовый тип, загрязнение области видимости и т.д.
➡️ Расширение возможностей с помощью итераторов-адаптеров
Итераторы-адаптеры - это классы, которые оборачивают стандартные итераторы и предоставляют дополнительные возможности или изменяют их поведение.• Итераторы-адаптеры предоставляют дополнительные возможности для работы с итераторами, такие как итерация в обратном порядке или фильтрация элементов.• Использование итераторов-адаптеров позволяет упростить код и делает его более читаемым за счет высокоуровневого интерфейса.• Итераторы-адаптеры добавляют гибкость в работу с контейнерами, позволяя выполнять сложные операции и манипуляции с элементами.
➡️ Ленивая инициализация статического объекта с использованием std::call_once
В многопоточных приложениях иногда требуется лениво инициализировать ресурсы, гарантируя, что это произойдет только один раз, даже если несколько потоков пытаются сделать это одновременно.
🗣️ Для этого можно использовать std::call_once.
➡️ Использование static_assert для компиляционных проверокstatic_assert — это мощный инструмент в C++, который позволяет проверять условия на этапе компиляции.• Он особенно полезен для проверки инвариантов, размеров типов или других свойств, которые должны быть выполнены перед компиляцией кода.
📂 Ввод-вывод в C: от fopen до системных вызовов
📅 4 сентября | 20:00 мск | бесплатно
На вебинаре разберём:
📜 Стандартные функции C: fopen, fread, fwrite, printf, scanf
⚡️ Буферизацию и почему fflush() не всегда срабатывает
🛠 Системные вызовы: read, write, open vs стандартная библиотека
🚫 Как избежать типичных ошибок при работе с файлами и потоками
Полезно для:
💡 Junior-разработчиков и тех, кто хочет глубже понять подсистему I/O в C и ОС
👉 Регистрируйтесь:
https://otus.pw/0rpE/
Занятие приурочено к старту курса "Программист С", обучение на котором позволит не только глубоко погрузиться в возможности языка С, но и изучить низкоуровневые особенности устройства UNIX-совместимых ОС и ОС семейства Windows
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
➡️ Универсальные ссылки• В официальной терминологии известные как forwarding references (передаваемые ссылки). Универсальная ссылка объявляется с помощью синтаксиса Т&&, где Т является шаблонным параметром типа, или с помощью auto&&. Они в свою очередь служат фундаментом для двух других крупных фич:• move-семантика• И perfect forwarding, возможность передавать аргументы, которые являются либо lvalue, либо rvalue.
Универсальные ссылки позволяют ссылаться на привязку либо к lvalue, либо к rvalue в зависимости от типа. Универсальные ссылки следуют правилам свертывания ссылок:1. T& & становится T& 2. T& && становится T&3. T&& & становится T&4. T&& && становится T&&
Вам нравится читать контент на этом канале?
Возможно, вы задумывались о том, чтобы купить на нем интеграцию?
Следуйте 3 простым шагам, чтобы сделать это:
1) Нажмите на ссылку: Вход
2) Пополняйтесь удобным способом
3) Размещайте публикацию
Если тематика вашего поста подойдет нашему каналу, мы с удовольствием опубликуем его.
➡️ Диапазоны и итераторы в C++• В C++ стандартная библиотека шаблонов (STL) предоставляет мощные инструменты для работы с коллекциями данных.• Диапазоны и итераторы позволяют вам легко и эффективно перебирать элементы контейнеров, таких как векторы, списки и множества.• Использование диапазонов и итераторов делает код более чистым и читаемым, упрощает операции перебора и модификации элементов контейнеров.
➡️ Модули (Modules) в C++
Модули - это система сборки и организации кода, представленная в C++20.• Они улучшают компиляцию и организацию кода, предоставляя более четкий и эффективный способ управления зависимостями.Модули заменяют использование препроцессорных директив #include, улучшая время компиляции и предотвращая проблемы с зависимостями и макросами.
• Модули значительно сокращают время компиляции по сравнению с традиционными заголовочными файлами, так как они компилируются только один раз.
• Модули предотвращают проблемы, связанные с макросами и конфликтами имен, поскольку они предоставляют четкие границы и изолированные области видимости.
• Модули упрощают управление зависимостями и организацию кода, что делает проекты более поддерживаемыми и масштабируемыми.
•
Snake – искусственный интеллект для игры «Змейка»
Цель змеи – постоянно есть пищу и как можно скорее заполнить карту своим телом
Первоначально проект был написан на C++. Теперь он был переписан на Python с удобным графическим интерфейсом для пользователя
https://github.com/chuyangliu/snake
#вопросы_с_собеседований
В чем проблема следующего фрагмента?
Из спецификации (C++11 §5.3.5/3):
Если статический тип подлежащего удалению объекта отличается от его динамического типа, статический тип должен быть базовым классом динамического типа подлежащего удалению объекта и иметь виртуальный деструктор или поведение undefined.
➡️ Библиотека PEGTL
PEGTL (Parsing Expression Grammar Template Library) — это библиотека для создания синтаксических анализаторов (парсеров) на C++. Она предоставляет мощные инструменты для определения грамматик и разбора текстов, что делает ее отличным выбором для создания языков программирования и обработки текстов.• PEGTL позволяет создавать сложные парсеры с минимальными усилиями, обеспечивая при этом высокую производительность и гибкость.
🔗 Ссылочка на доку
➡️ Библиотека SQLiteCpp
SQLiteCpp — это тонкая обертка вокруг SQLite, одной из самых популярных легковесных реляционных баз данных. Библиотека предоставляет удобный и безопасный интерфейс для работы с SQLite в C++, облегчая взаимодействие с базами данных.• Если вам нужно встроить простую, но мощную базу данных в ваше C++ приложение, SQLiteCpp — это то, что вам нужно.
🔗 Ссылочка на доку
SourceCraft запустил конкурс репозиториев и прием заявок на грантовую программу.
Загружайте проекты, собирайте отклики сообщества и получайте шанс попасть в число лучших.
Система многоуровневых оценок и ачивки в профиле помогают сделать вклад разработчиков заметным, а экспертам — увидеть перспективные идеи.
Платформа помогает сократить путь от идеи до релиза: код, тесты, сборка и выкатывание продукта делаются быстрее и удобнее прямо в SourceCraft.
Информация об организаторе Акции, о правилах проведения Акции, количестве призов, сроках, месте и порядке их получения размещена по ссылке.
➡️ Оптимизация работы с большими объектами с помощью std::move и семантики перемещенияstd::move — это функция, которая превращает объект в "rvalue" (правостороннее значение), позволяя использовать семантику перемещения вместо копирования. Это особенно полезно при работе с большими объектами, где копирование может быть дорогим.• В этом примере используется std::move, чтобы передать большой объект LargeObject в функцию processLargeObject с использованием семантики перемещения. Вместо дорогостоящего копирования большого массива, память просто передается новому объекту, что значительно улучшает производительность.