•
В C++ имя функции пользовательских операторов — это сам символ оператора.•
Унарные и бинарные операторы (- и -) различаются по количеству аргументов.•
Унарные операторы инкремента и декремента (++, --) имеют одинаковую сигнатуру.•
Для различия постфиксных операторов ++ и -- используется фиктивный аргумент int.•
Постфиксные операторы ++ и -- принимают фиктивный аргумент int как флаг для компилятора.Please open Telegram to view this post
VIEW IN TELEGRAM
•
C++ позволяет вызывать статические методы из экземпляра таким же образом, как и из класса. •
Это позволяет изменять нестатические методы экземпляра на статические без необходимости обновления записи вызова функции.Please open Telegram to view this post
VIEW IN TELEGRAM
•
Перегрузка операторов , (запятая), || (логическое ИЛИ), и && (логическое И) сбивает с толку.•
Оператор «запятая» обычно гарантирует, что левая сторона вычисляется до правой.•
Операторы || и && обычно вычисляют правую сторону только при необходимости.•
Перегруженные версии этих операторов — это вызовы функций, которые вычисляются в неопределенном порядке.•
Перегрузка этих операторов может привести к некорректному использованию синтаксиса C++.Please open Telegram to view this post
VIEW IN TELEGRAM
•
C++11 позволяет перегружать методы с использованием квалификатора ссылки, который находится в той же позиции, что и cv-квалификаторы (const и volatile квалификаторы).•
Это влияет на то, какой метод будет вызван для объекта, в зависимости от типа this
, – является ли он lvalue
или же rvalue
.Please open Telegram to view this post
VIEW IN TELEGRAM
C++ включает синтаксическое сокращение для одновременного объявления переменной и разветвления по её значению.
•
Это выглядит как декларация переменной внутри условия оператора if
или while
, и одновременное присваивание ей значения.Please open Telegram to view this post
VIEW IN TELEGRAM
•
Размещающий new - это альтернативный синтаксис для оператора new, который размещает объект в уже выделенной памяти. Он используется для настройки vtable
и вызова конструктора.•
Размещающий new полезен для написания кастомных аллокаторов, оптимизирующих производительность. Он позволяет выделить большой блок памяти и последовательно размещать объекты без пробелов, что уменьшает фрагментацию памяти и снижает накладные расходы.Please open Telegram to view this post
VIEW IN TELEGRAM
•
Переопределение ключевых слов — плохая практика программирования, но это возможно через препроцессор. Это может вводить баги, например, #define true false
или #define else
.#define int float
#define float char
•
Такой код будет работать, хотя это может быть полезно в некоторых ситуациях. Например, если мы используем большую библиотеку и не хотим публичного наследования, мы можем временно отключить защиту доступа перед подключением заголовков библиотеки, а затем снова включить её.#define public private
#include "mylibrary.h"
#undef private
•
Это позволяет управлять доступом к библиотеке без её изменения, но требует осторожности.Please open Telegram to view this post
VIEW IN TELEGRAM
Lambda-функции — это мощный инструмент в C++, позволяющий определять анонимные функции прямо в месте их использования.
•
Они особенно полезны для создания компактного и читаемого кода, например, при работе с алгоритмами из стандартной библиотеки (STL).Please open Telegram to view this post
VIEW IN TELEGRAM
•
Типобезопасные перечисления, которые решают множество проблем с C-перечислениями, включая неявные преобразования, арифметические операции, невозможность указать базовый тип, загрязнение области видимости и т.д.Please open Telegram to view this post
VIEW IN TELEGRAM
•
Использование private и public при наследовании в C++ позволяет контролировать доступ к членам базового класса в производных классах.•
Это может быть полезно для сокрытия частей реализации базового класса от внешнего мира или ограничения доступа к членам в иерархии классов.•
Эта фишка особенно полезна при проектировании классов и их взаимодействия, позволяя более гибко управлять доступом к данным и методам в рамках наследования.Please open Telegram to view this post
VIEW IN TELEGRAM
Итераторы-адаптеры - это классы, которые оборачивают стандартные итераторы и предоставляют дополнительные возможности или изменяют их поведение.
•
Итераторы-адаптеры предоставляют дополнительные возможности для работы с итераторами, такие как итерация в обратном порядке или фильтрация элементов.•
Использование итераторов-адаптеров позволяет упростить код и делает его более читаемым за счет высокоуровневого интерфейса.•
Итераторы-адаптеры добавляют гибкость в работу с контейнерами, позволяя выполнять сложные операции и манипуляции с элементами.Please open Telegram to view this post
VIEW IN TELEGRAM
•
Параметром шаблона могут быть конкретные целые числа.•
Параметром шаблона также могут быть конкретные функции.•
Это позволяет компилятору встраивать вызовы для этих функций в коде инстанцированного шаблона для более эффективного выполнения.•
В примере ниже, функция memoize()
в качестве шаблонного параметра получает функцию и вызывает эту функцию для новых значений аргумента.•
Старое сохранённое значение аргумента берётся из кеша.Please open Telegram to view this post
VIEW IN TELEGRAM
В многопоточных приложениях иногда требуется лениво инициализировать ресурсы, гарантируя, что это произойдет только один раз, даже если несколько потоков пытаются сделать это одновременно.
std::call_once
.Please open Telegram to view this post
VIEW IN TELEGRAM
В C++ утечки памяти могут стать серьезной проблемой, особенно в больших проектах. Один из способов обнаружения утечек памяти — переопределение оператора new, чтобы отслеживать выделение и освобождение памяти.
•
Мы переопределяем оператор new, чтобы отслеживать все выделения памяти, сохраняя указатели и размеры выделенных блоков в std::map
.•
Переопределение оператора delete позволяет отслеживать освобождение памяти. Когда память освобождается, соответствующая запись удаляется из allocations
.•
В конце программы проверяется, остались ли неосвобожденные участки памяти, что позволяет обнаружить утечки.Please open Telegram to view this post
VIEW IN TELEGRAM
В C++ оператор
decltype
позволяет определить тип переменной на основе типа другого выражения. Это особенно полезно в шаблонном программировании для создания зависимых типов, когда точный тип заранее неизвестен.•
Оператор decltype
определяет тип sum на основе типа элементов, возвращаемых итератором контейнера. Это позволяет избежать жесткого кодирования типов и делает код более гибким.•
Использование decltype
в шаблонных функциях позволяет писать более универсальный код, который корректно работает с различными типами контейнеров.Please open Telegram to view this post
VIEW IN TELEGRAM
SFINAE (Substitution Failure Is Not An Error) — это одна из самых мощных и менее известных техник в C++, которая позволяет выбирать, какие функции должны быть скомпилированы, на основе доступности определенных типов или выражений.
•
SFINAE позволяет автоматически исключать функции из компиляции, если параметры или выражения не соответствуют определенным условиям. Это достигается с помощью специальных инструментов, таких как std::enable_if
.•
В примере выше используются std::enable_if_t
и std::is_integral_v
для выбора функции, которая будет скомпилирована, на основе типа передаваемого аргумента.•
SFINAE делает код более универсальным и позволяет использовать единую функцию для обработки различных типов данных, выбирая правильную реализацию на этапе компиляции.Please open Telegram to view this post
VIEW IN TELEGRAM
static_assert
— это мощный инструмент в C++, который позволяет проверять условия на этапе компиляции.•
Он особенно полезен для проверки инвариантов, размеров типов или других свойств, которые должны быть выполнены перед компиляцией кода.C++ Learning
Please open Telegram to view this post
VIEW IN TELEGRAM
•
Приведение в стиле 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, явное преобразование, вы знаете, что делаете
Please open Telegram to view this post
VIEW IN TELEGRAM
•
Синтаксический сахар для перебора элементов контейнера.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 }
Please open Telegram to view this post
VIEW IN TELEGRAM