Senior C++ Developer – Telegram
Senior C++ Developer
12.3K subscribers
1.36K photos
3 videos
609 links
Изучаем C++.

По вопросам сотрудничества: @adv_and_pr

РКН: https://www.gosuslugi.ru/snet/676e9a1e4e740947beca35ba
Download Telegram
#вопросы_с_собеседований
Что случится, если вернуть ссылку на временный объект?

Если вернуть ссылку на временный объект, созданный в стеке, то это приведет к неопределенному поведению программы.

После выхода из функции память, выделенная под временный объект, освобождается. И если где-то сохранилась ссылка на этот объект, то при попытке обратиться к нему произойдет ошибка.
string.back

Эта функция возвращает ссылку на последний символ строки.
Она позволяет получить доступ к последнему символу строки и при необходимости изменить его.

Возвращаемое значение имеет тип символа строки, обычно char или wchar_t. Если строка пустая, то поведение функции неопределенно, поэтому нужно проверять, что строка не пуста, прежде чем вызывать back().

string.back часто используется в циклах для обработки символов строки с конца или для проверки последнего символа.

#это_база
void указатели

Void указатель (void*) — это не типизированный указатель, который может указывать на объект любого типа.
Void указатели могут приводиться к любому другому типу указателей и обратно без явного преобразования.

Арифметические операции недопустимы для void указателей, так как компилятор не знает размер объекта в памяти. При их использовании нужно следить за типобезопасностью и правильностью приведений типов.

В основном void указатели используются для обобщенной работы с указателями разных типов. Например, в функциях реализующих общие алгоритмы.

#это_база
Исключение std::bad_any_cast

Исключение std::bad_any_cast выбрасывается при неудачной попытке приведения типа any к другому типу. Это происходит, когда тип, к которому производится приведение, не соответствует реальному типу объекта, хранящегося в any.

Например, если в any хранится объект типа int, а мы пытаемся привести его к типу std::string, то будет выброшено исключение bad_any_cast.
Это исключение позволяет обнаружить ошибки при использовании any во время выполнения программы.

Таким образом, bad_any_cast гарантирует типобезопасность при работе с any и указывает на то, что при приведении типов была допущена ошибка.
Чтобы избежать этого исключения, нужно проверять тип объекта в any с помощью any_cast перед приведением типа.
emplace_back

Функция emplace_back используется для вставки нового элемента в конец контейнера типа std::vector или std::list.

Отличие от обычного push_back заключается в том, что emplace_back конструирует новый элемент прямо на месте, в то время как push_back сначала создает временный объект, а затем перемещает его в контейнер.

Преимущества emplace_back:
— Позволяет избежать лишних операций копирования или перемещения объектов при вставке. Объект создается сразу на месте.
— Может принимать аргументы для конструктора вставляемого объекта. У push_back только один параметр — сам объект.
— Более эффективно для классов без определенного конструктора копирования или перемещения.

Таким образом, emplace_back позволяет оптимизировать вставку элементов в вектор или список за счет создания объекта прямо на месте.
Это полезно при работе с классами, которые дороги в копировании/перемещении или требуют параметры для конструирования.
#вопросы_с_собеседований
Что будет, если забыть вызвать delete?

Если в программе забыть вызвать оператор delete при динамическом выделении памяти с помощью new, это приведет к утечке памяти.

Выделенная динамически область памяти не будет возвращена системе и останется занятой до завершения программы. При многократном выделении памяти без освобождения может закончиться свободная память в куче и программа аварийно завершится.
Также "зависшая" память может привести к фрагментации кучи. Это усложнит выделение крупных последовательных блоков памяти в дальнейшем.

Поэтому очень важно правильно выделять и освобождать память во избежание утечек. Лучше всего использовать умные указатели, которые автоматически вызывают delete, или контейнеры, управляющие памятью за программиста.
#вопросы_с_собеседований
Что такое делегирующий конструктор?

Делегирующий конструктор — это конструктор, который вызывает другой конструктор того же класса для инициализации объекта.
Это позволяет избежать дублирования кода инициализации при написании нескольких конструкторов для одного класса.

Например, если в классе определен конструктор с двумя параметрами, то конструктор с одним параметром может просто вызывать первый конструктор, передавая какое-то значение по умолчанию в качестве второго параметра.
Алгоритм mismatch

Mismatch — это алгоритм из стандартной библиотеки, который сравнивает два диапазона и возвращает итераторы на первые несовпадающие элементы.

Он принимает 4 параметра:
— Итераторы на начало двух диапазонов для сравнения.
— Итераторы на конец этих диапазонов.
— Бинарный предикат для сравнения элементов (по умолчанию используется оператор ==).

Алгоритм идет по двум диапазонам параллельно и сравнивает элементы с помощью предиката. Как только элементы не совпадут, алгоритм вернет пару итераторов на эти элементы.
Если диапазоны закончились, а элементы так и не отличились, то возвращаются итераторы на конец диапазонов.

Этот алгоритм полезен для поиска различий в двух последовательностях.

#это_база
is_sorted_until

Этот алгоритм проверяет, отсортирован ли заданный диапазон данных.
Он возвращает итератор на первый элемент, нарушающий порядок сортировки.

Алгоритм принимает 3 параметра:
— Итератор на начало проверяемого диапазона.
— Итератор на конец диапазона.
— Компаратор для сравнения элементов (по умолчанию less).

Алгоритм идет по диапазону от начала к концу и сравнивает каждый элемент с предыдущим с помощью компаратора.
Если нарушения порядка не найдено, возвращается итератор на конец диапазона. Иначе возвращается итератор на первый нарушающий элемент.

Этот алгоритм удобен, чтобы проверить, в какой момент отсортированный диапазон теряет порядок.

#это_база
Библиотека концепций

Библиотека концепций (concepts library) — это новая библиотека, добавленная в C++20 для работы с концепциями.

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

Концепции используются для:
— Проверки корректности типов в шаблонах функций и классов.
— Ограничения диапазона допустимых типов.
— Улучшения сообщений об ошибках компиляции.
— Возможности оптимизации кода компилятором.

В примере концепция equality_comparable используется для проверки, что тип T поддерживает операцию ==, необходимую для сортировки. Это позволяет выявить ошибку на этапе компиляции.
std::size_t

std::size_t — это тип данных без знака, предназначенный для хранения размера объектов в памяти.
Он определен в заголовочном файле <cstddef> и обычно представлен как unsigned int или unsigned long в зависимости от платформы.

std::size_t используется для:
— Представления индексов массивов и размеров контейнеров в стандартной библиотеке.
— Возврата значений размера из функций, например size(), length().
— Указания размера при выделении памяти.
— Предотвращения переполнения при вычислениях размеров.

std::size_t гарантирует достаточный диапазон значений для адресации всей доступной памяти.
#вопросы_с_собеседований
Какая разница между calloc и malloc?

Основное различие между функциями calloc и malloc заключается в том, как они инициализируют выделенную память.

malloc просто выделяет указанный объем памяти и возвращает указатель на него. Содержимое выделенной памяти при этом не инициализируется.
calloc, помимо выделения памяти, также инициализирует всю выделенную память нулями. Таким образом после вызова calloc вся выделенная память будет заполнена нулевыми значениями.

Кроме того, в calloc размер выделяемой памяти задается в элементах, а не в байтах. Calloc умножает количество элементов на размер одного элемента, чтобы определить общий размер памяти для выделения.
#вопросы_с_собеседований
Что такое список инициализации?

Список инициализации — это способ инициализации переменных, при котором переменные инициализируются прямо в месте их объявления через список инициализаторов в фигурных скобках {}.
При использовании списка инициализации переменные инициализируются сразу при объявлении, а не в отдельном операторе присваивания.

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

Алгоритм lower_bound — это алгоритм поиска в отсортированном массиве или контейнере элемента, который не меньше заданного значения.

lower_bound возвращает итератор на первый элемент в диапазоне, который не меньше заданного значения. Если подходящий элемент не найден, возвращается итератор на конец диапазона.
При этом массив или контейнер должен быть отсортирован.

Алгоритм имеет логарифмическую сложность O(log n).
Может применяться для поиска элемента или вставки нового элемента в отсортированный массив

#это_база
Пространство имен

Пространства имен позволяют группировать объекты (классы, функции, переменные) под общим уникальным именем.
Это избавляет от конфликтов имен при использовании кода из разных библиотек.

Пространства имен объявляются конструкцией namespace, а чтобы использовать объект из пространства имен, нужно указывать полное имя с именем пространства.
Чтобы не писать префикс каждый раз можно импортировать пространство имен в начале файла.

#это_база
requires-expression

Requires-выражение в С++20 позволяет задавать требования к типам параметров шаблонов.
Это дает возможность выполнять проверку типов во время компиляции и позволяет создавать перегруженные шаблоны функций и классов с разными требованиями к типам.

Requires-expressions помогают создавать более гибкие и безопасные шаблоны, улучшают читаемость кода и помогают компилятору генерировать более качественные сообщения об ошибках.

В примере для каждой перегрузки функции add используется requires-выражение, которое накладывает ограничения на тип параметра T.
Это позволяет компилятору выбрать нужную перегрузку в зависимости от типа аргументов.
requires clause

requires clause в С++20 — это новый синтаксис для задания требований к шаблонам, альтернативный requires-выражениям.

requires clause позволяет задавать требования к типам непосредственно при объявлении шаблона. Это делает код более читабельным и понятным.

Requires clause применяется для:
— Проверки наличия определенных возможностей у типов-параметров шаблонов.
— Ограничения допустимых типов-параметров.
— Условного компилирования шаблонов в зависимости от типов.

В примере requires clause гарантирует, что функция add будет работать только с целочисленными типами.
Это делает намерения программиста явными и позволяет лучше контролировать вызовы шаблона.
#вопросы_с_собеседований
Какие есть способы инициализации полей класса?

В C++ есть несколько способов инициализации полей класса:

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

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

Инициализационный список: позволяет проинициализировать поля до вызова тела конструктора.

Значения по умолчанию: для базовых типов компилятор сам присвоит значения по умолчанию, если не указано иное.

Статическая инициализация: для статических полей класса можно задать начальное значение непосредственно при объявлении.

Каждый из этих способов имеет свои особенности и подходит для разных случаев инициализации полей класса.
#вопросы_с_собеседований
Что такое "идиома remove-erase"?

Идиома remove-erase — это распространенный прием работы с контейнерами, позволяющий эффективно удалять элементы, соответствующие некоторому условию.

Суть идиомы заключается в следующем:

1. С помощью алгоритма std::remove или std::remove_if элементы, подлежащие удалению, перемещаются в конец контейнера.
2. Затем с помощью метода erase удаляется диапазон элементов от нового конца контейнера до старого, содержащий элементы для удаления.
3. Такой подход позволяет избежать лишних копирований, так как при удалении с помощью erase порядок оставшихся элементов сохраняется.

Эта идиома часто используется для эффективного удаления элементов из вектора или других последовательных контейнеров.
Шаблон Voodoo

Шаблон Voodoo — это шаблон проектирования, который используется для связывания объектов во время выполнения программы.
Шаблон довольно гибкий и позволяет создавать сложные отношения между объектами.

Voodoo использует композицию объектов вместо наследования. Объекты связываются друг с другом через указатели или ссылки.
Один объект выступает в роли родительского, остальные — в роли детей. Дети могут обращаться к родителю, но не наоборот. Связи между объектами устанавливаются динамически во время выполнения программы.

#это_база
Алгоритм find_if_not

Алгоритм find_if_not — это алгоритм поиска в диапазоне, который ищет первый элемент, НЕ удовлетворяющий условию.
Он принимает начало и конец диапазона, а также унарный предикат (условие), возвращает итератор на первый найденный элемент, не соответствующий предикату. Если такого элемента нет — возвращает итератор на конец диапазона.

Алгоритм работает с разными типами контейнеров, поддерживающих итераторы.

#это_база