#вопросы_с_собеседований
Как изменить поле класса в константном методе класса?
В константном методе класса нельзя изменить значение поля, объявленного как const.
Однако, можно изменить поле, объявленное без ключевого слова const, даже внутри const метода. Хотя это и не рекомендуется, так как нарушает идею неизменяемости объекта в константном контексте.
Чтобы все же иметь возможность модифицировать поля внутри const метода, можно объявить нужные поля как mutable. Тогда компилятор разрешит изменять эти поля, даже если вызов осуществляется на константный объект и из константного метода.
Но использование mutable стоит ограничивать, по возможности избегая. Лучше пересмотреть структуру класса, чтобы константные методы не нуждались в изменении полей.
Как изменить поле класса в константном методе класса?
Однако, можно изменить поле, объявленное без ключевого слова const, даже внутри const метода. Хотя это и не рекомендуется, так как нарушает идею неизменяемости объекта в константном контексте.
Чтобы все же иметь возможность модифицировать поля внутри const метода, можно объявить нужные поля как mutable. Тогда компилятор разрешит изменять эти поля, даже если вызов осуществляется на константный объект и из константного метода.
Но использование mutable стоит ограничивать, по возможности избегая. Лучше пересмотреть структуру класса, чтобы константные методы не нуждались в изменении полей.
std::any_cast
Класс
Чтобы получить эти данные обратно в изначальный тип, и используется
Если совместим — возвращает ссылку на данные нужного типа.
Например, если в
std::any_cast используется для приведения объектов типа std::any к конкретному типу данных во время выполнения программы. Класс
std::any может хранить данные любого типа, но при этом теряется информация о реальном типе данных. Чтобы получить эти данные обратно в изначальный тип, и используется
std::any_cast. Он проверяет, совместим ли хранимый в std::any объект с запрошенным целевым типом. Если совместим — возвращает ссылку на данные нужного типа.
Например, если в
std::any был помещен объект типа int, то с помощью std::any_cast этот int можно получить обратно в переменную типа int. Аналогично для других типов данных.Функция value_or
Функция
Класс
Чтобы получить это значение из
Чтобы избежать исключения при отсутствии значения, можно воспользоваться функцией
Если в
Функция
value_or используется для получения значения из объекта типа std::optional. Класс
std::optional позволяет хранить значение или отсутствие значения. Чтобы получить это значение из
optional, обычно используют метод value(). Но если значения нет, это выбросит исключение.Чтобы избежать исключения при отсутствии значения, можно воспользоваться функцией
value_or. Она принимает объект std::optional и значение по умолчанию. Если в
optional есть значение — возвращается оно. Если значения нет — возвращается значение по умолчанию.memset
Она принимает указатель на блок памяти, значение байта для заполнения и размер блока в байтах.
Необходимо быть осторожным с типами данных, т. к.
#это_база
memset используется для заполнения блока памяти одним значением байта. Она принимает указатель на блок памяти, значение байта для заполнения и размер блока в байтах.
memset полезна для быстрого обнуления или заполнения блоков памяти.Необходимо быть осторожным с типами данных, т. к.
memset работает на уровне байтов.#это_база
std::swap
Функция принимает ссылки на две переменные типа T. Меняет их местами.
Работает с любыми типами данных, которые поддерживают оператор присваивания. Может быть перегружен для пользовательских типов данных.
Также стандартная библиотека С++ содержит специализированные версии
Часто используется вместо ручного обмена значениями с помощью третьей переменной.
#это_база
std::swap находится в заголовочном файле <utility> и используется для обмена значениями двух переменных одного типа.Функция принимает ссылки на две переменные типа T. Меняет их местами.
Работает с любыми типами данных, которые поддерживают оператор присваивания. Может быть перегружен для пользовательских типов данных.
Также стандартная библиотека С++ содержит специализированные версии
swap для контейнеров.Часто используется вместо ручного обмена значениями с помощью третьей переменной.
#это_база
#вопросы_с_собеседований
Что будет, если дважды вызвать free?
Если вызвать free два раза для одного и того же участка памяти, это приведет к неопределенному поведению программы и скорее всего к ее аварийному завершению.
При первом вызове free освобождается участок памяти и возвращается в кучу для последующего выделения.
При повторном вызове для того же участка менеджер памяти попытается освободить уже освобождённую область.
Это приведет к повреждению структур данных менеджера памяти и неопределенному поведению — от тихих ошибок вроде утечек памяти, до полного сбоя и аварийного завершения программы.
Что будет, если дважды вызвать free?
При первом вызове free освобождается участок памяти и возвращается в кучу для последующего выделения.
При повторном вызове для того же участка менеджер памяти попытается освободить уже освобождённую область.
Это приведет к повреждению структур данных менеджера памяти и неопределенному поведению — от тихих ошибок вроде утечек памяти, до полного сбоя и аварийного завершения программы.
#вопросы_с_собеседований
Расскажите о битовых полях.
Битовые поля (bit fields) — это возможность в С++ объявить структуру или класс, в котором отдельные члены занимают указанное количество бит.
Это позволяет эффективно использовать память для хранения флагов, битовых масок и других небольших значений.
При обращении к этим полям происходят битовые операции. Можно устанавливать, сбрасывать биты, проверять их состояние.
Битовые поля позволяют гибко упаковывать данные и экономить память.
Но их использование усложняет код, делает его менее читабельным. Поэтому нужно применять с осторожностью, только когда экономия памяти критична.
Расскажите о битовых полях.
Это позволяет эффективно использовать память для хранения флагов, битовых масок и других небольших значений.
При обращении к этим полям происходят битовые операции. Можно устанавливать, сбрасывать биты, проверять их состояние.
Битовые поля позволяют гибко упаковывать данные и экономить память.
Но их использование усложняет код, делает его менее читабельным. Поэтому нужно применять с осторожностью, только когда экономия памяти критична.
#вопросы_с_собеседований
Какие методы можно вызвать из константных объектов?
Из константных объектов можно вызывать только константные методы — методы, которые помечены ключевым словом const.
Константные методы не меняют состояние объекта, а только читают данные. Они гарантируют, что работа с объектом будет безопасной.
Неконстантные же методы могут изменять состояние объекта. Их нельзя вызвать из константного объекта, чтобы избежать непреднамеренного изменения объекта.
Таким образом константность защищает объект от изменений там, где это нужно. А разделение на константные и неконстантные методы дает возможность гибко управлять доступом к данным в объекте.
Какие методы можно вызвать из константных объектов?
Константные методы не меняют состояние объекта, а только читают данные. Они гарантируют, что работа с объектом будет безопасной.
Неконстантные же методы могут изменять состояние объекта. Их нельзя вызвать из константного объекта, чтобы избежать непреднамеренного изменения объекта.
Таким образом константность защищает объект от изменений там, где это нужно. А разделение на константные и неконстантные методы дает возможность гибко управлять доступом к данным в объекте.
#вопросы_с_собеседований
Что случится, если вернуть ссылку на временный объект?
Если вернуть ссылку на временный объект, созданный в стеке, то это приведет к неопределенному поведению программы.
После выхода из функции память, выделенная под временный объект, освобождается. И если где-то сохранилась ссылка на этот объект, то при попытке обратиться к нему произойдет ошибка.
Что случится, если вернуть ссылку на временный объект?
После выхода из функции память, выделенная под временный объект, освобождается. И если где-то сохранилась ссылка на этот объект, то при попытке обратиться к нему произойдет ошибка.
string.back
Эта функция возвращает ссылку на последний символ строки.
Она позволяет получить доступ к последнему символу строки и при необходимости изменить его.
Возвращаемое значение имеет тип символа строки, обычно
#это_база
Эта функция возвращает ссылку на последний символ строки.
Она позволяет получить доступ к последнему символу строки и при необходимости изменить его.
Возвращаемое значение имеет тип символа строки, обычно
char или wchar_t. Если строка пустая, то поведение функции неопределенно, поэтому нужно проверять, что строка не пуста, прежде чем вызывать back().string.back часто используется в циклах для обработки символов строки с конца или для проверки последнего символа.#это_база
void указатели
Void указатель (
Void указатели могут приводиться к любому другому типу указателей и обратно без явного преобразования.
Арифметические операции недопустимы для void указателей, так как компилятор не знает размер объекта в памяти. При их использовании нужно следить за типобезопасностью и правильностью приведений типов.
В основном void указатели используются для обобщенной работы с указателями разных типов. Например, в функциях реализующих общие алгоритмы.
#это_база
Void указатель (
void*) — это не типизированный указатель, который может указывать на объект любого типа.Void указатели могут приводиться к любому другому типу указателей и обратно без явного преобразования.
Арифметические операции недопустимы для void указателей, так как компилятор не знает размер объекта в памяти. При их использовании нужно следить за типобезопасностью и правильностью приведений типов.
В основном void указатели используются для обобщенной работы с указателями разных типов. Например, в функциях реализующих общие алгоритмы.
#это_база
Исключение std::bad_any_cast
Исключение std::bad_any_cast выбрасывается при неудачной попытке приведения типа any к другому типу. Это происходит, когда тип, к которому производится приведение, не соответствует реальному типу объекта, хранящегося в
Например, если в
Это исключение позволяет обнаружить ошибки при использовании
Таким образом,
Чтобы избежать этого исключения, нужно проверять тип объекта в any с помощью
Исключение 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.
Отличие от обычного
Преимущества
— Позволяет избежать лишних операций копирования или перемещения объектов при вставке. Объект создается сразу на месте.
— Может принимать аргументы для конструктора вставляемого объекта. У
— Более эффективно для классов без определенного конструктора копирования или перемещения.
Таким образом,
Это полезно при работе с классами, которые дороги в копировании/перемещении или требуют параметры для конструирования.
Функция emplace_back используется для вставки нового элемента в конец контейнера типа std::vector или std::list.
Отличие от обычного
push_back заключается в том, что emplace_back конструирует новый элемент прямо на месте, в то время как push_back сначала создает временный объект, а затем перемещает его в контейнер.Преимущества
emplace_back:— Позволяет избежать лишних операций копирования или перемещения объектов при вставке. Объект создается сразу на месте.
— Может принимать аргументы для конструктора вставляемого объекта. У
push_back только один параметр — сам объект.— Более эффективно для классов без определенного конструктора копирования или перемещения.
Таким образом,
emplace_back позволяет оптимизировать вставку элементов в вектор или список за счет создания объекта прямо на месте. Это полезно при работе с классами, которые дороги в копировании/перемещении или требуют параметры для конструирования.
#вопросы_с_собеседований
Что будет, если забыть вызвать delete?
Если в программе забыть вызвать оператор delete при динамическом выделении памяти с помощью new, это приведет к утечке памяти.
Выделенная динамически область памяти не будет возвращена системе и останется занятой до завершения программы. При многократном выделении памяти без освобождения может закончиться свободная память в куче и программа аварийно завершится.
Также "зависшая" память может привести к фрагментации кучи. Это усложнит выделение крупных последовательных блоков памяти в дальнейшем.
Поэтому очень важно правильно выделять и освобождать память во избежание утечек. Лучше всего использовать умные указатели, которые автоматически вызывают delete, или контейнеры, управляющие памятью за программиста.
Что будет, если забыть вызвать delete?
Выделенная динамически область памяти не будет возвращена системе и останется занятой до завершения программы. При многократном выделении памяти без освобождения может закончиться свободная память в куче и программа аварийно завершится.
Также "зависшая" память может привести к фрагментации кучи. Это усложнит выделение крупных последовательных блоков памяти в дальнейшем.
Поэтому очень важно правильно выделять и освобождать память во избежание утечек. Лучше всего использовать умные указатели, которые автоматически вызывают delete, или контейнеры, управляющие памятью за программиста.
#вопросы_с_собеседований
Что такое делегирующий конструктор?
Делегирующий конструктор — это конструктор, который вызывает другой конструктор того же класса для инициализации объекта.
Это позволяет избежать дублирования кода инициализации при написании нескольких конструкторов для одного класса.
Например, если в классе определен конструктор с двумя параметрами, то конструктор с одним параметром может просто вызывать первый конструктор, передавая какое-то значение по умолчанию в качестве второго параметра.
Что такое делегирующий конструктор?
Это позволяет избежать дублирования кода инициализации при написании нескольких конструкторов для одного класса.
Например, если в классе определен конструктор с двумя параметрами, то конструктор с одним параметром может просто вызывать первый конструктор, передавая какое-то значение по умолчанию в качестве второго параметра.
Алгоритм mismatch
Mismatch — это алгоритм из стандартной библиотеки, который сравнивает два диапазона и возвращает итераторы на первые несовпадающие элементы.
Он принимает 4 параметра:
— Итераторы на начало двух диапазонов для сравнения.
— Итераторы на конец этих диапазонов.
— Бинарный предикат для сравнения элементов (по умолчанию используется оператор ==).
Алгоритм идет по двум диапазонам параллельно и сравнивает элементы с помощью предиката. Как только элементы не совпадут, алгоритм вернет пару итераторов на эти элементы.
Если диапазоны закончились, а элементы так и не отличились, то возвращаются итераторы на конец диапазонов.
Этот алгоритм полезен для поиска различий в двух последовательностях.
#это_база
Mismatch — это алгоритм из стандартной библиотеки, который сравнивает два диапазона и возвращает итераторы на первые несовпадающие элементы.
Он принимает 4 параметра:
— Итераторы на начало двух диапазонов для сравнения.
— Итераторы на конец этих диапазонов.
— Бинарный предикат для сравнения элементов (по умолчанию используется оператор ==).
Алгоритм идет по двум диапазонам параллельно и сравнивает элементы с помощью предиката. Как только элементы не совпадут, алгоритм вернет пару итераторов на эти элементы.
Если диапазоны закончились, а элементы так и не отличились, то возвращаются итераторы на конец диапазонов.
Этот алгоритм полезен для поиска различий в двух последовательностях.
#это_база
is_sorted_until
Этот алгоритм проверяет, отсортирован ли заданный диапазон данных.
Он возвращает итератор на первый элемент, нарушающий порядок сортировки.
Алгоритм принимает 3 параметра:
— Итератор на начало проверяемого диапазона.
— Итератор на конец диапазона.
— Компаратор для сравнения элементов (по умолчанию
Алгоритм идет по диапазону от начала к концу и сравнивает каждый элемент с предыдущим с помощью компаратора.
Если нарушения порядка не найдено, возвращается итератор на конец диапазона. Иначе возвращается итератор на первый нарушающий элемент.
Этот алгоритм удобен, чтобы проверить, в какой момент отсортированный диапазон теряет порядок.
#это_база
Этот алгоритм проверяет, отсортирован ли заданный диапазон данных.
Он возвращает итератор на первый элемент, нарушающий порядок сортировки.
Алгоритм принимает 3 параметра:
— Итератор на начало проверяемого диапазона.
— Итератор на конец диапазона.
— Компаратор для сравнения элементов (по умолчанию
less).Алгоритм идет по диапазону от начала к концу и сравнивает каждый элемент с предыдущим с помощью компаратора.
Если нарушения порядка не найдено, возвращается итератор на конец диапазона. Иначе возвращается итератор на первый нарушающий элемент.
Этот алгоритм удобен, чтобы проверить, в какой момент отсортированный диапазон теряет порядок.
#это_база
Библиотека концепций
Библиотека концепций (concepts library) — это новая библиотека, добавленная в C++20 для работы с концепциями.
Концепции позволяют формально определять требования к типам. Они похожи на шаблоны, но проверяют не только наличие определенных операций, но и семантику этих операций.
Концепции используются для:
— Проверки корректности типов в шаблонах функций и классов.
— Ограничения диапазона допустимых типов.
— Улучшения сообщений об ошибках компиляции.
— Возможности оптимизации кода компилятором.
В примере концепция
Библиотека концепций (concepts library) — это новая библиотека, добавленная в C++20 для работы с концепциями.
Концепции позволяют формально определять требования к типам. Они похожи на шаблоны, но проверяют не только наличие определенных операций, но и семантику этих операций.
Концепции используются для:
— Проверки корректности типов в шаблонах функций и классов.
— Ограничения диапазона допустимых типов.
— Улучшения сообщений об ошибках компиляции.
— Возможности оптимизации кода компилятором.
В примере концепция
equality_comparable используется для проверки, что тип T поддерживает операцию ==, необходимую для сортировки. Это позволяет выявить ошибку на этапе компиляции.std::size_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 умножает количество элементов на размер одного элемента, чтобы определить общий размер памяти для выделения.
Какая разница между calloc и malloc?
malloc просто выделяет указанный объем памяти и возвращает указатель на него. Содержимое выделенной памяти при этом не инициализируется.
calloc, помимо выделения памяти, также инициализирует всю выделенную память нулями. Таким образом после вызова calloc вся выделенная память будет заполнена нулевыми значениями.
Кроме того, в calloc размер выделяемой памяти задается в элементах, а не в байтах. Calloc умножает количество элементов на размер одного элемента, чтобы определить общий размер памяти для выделения.
#вопросы_с_собеседований
Что такое список инициализации?
Список инициализации — это способ инициализации переменных, при котором переменные инициализируются прямо в месте их объявления через список инициализаторов в фигурных скобках {}.
При использовании списка инициализации переменные инициализируются сразу при объявлении, а не в отдельном операторе присваивания.
Преимущества списка инициализации:
— Переменная всегда инициализирована, нет возможности использовать неинициализированную переменную.
— Компилятор может выполнить оптимизации, т. к. знает значение переменной при инициализации.
— При инициализации классов вызываются нужные конструкторы.
— Код становится более читабельным, инициализация видна сразу при объявлении.
Что такое список инициализации?
При использовании списка инициализации переменные инициализируются сразу при объявлении, а не в отдельном операторе присваивания.
Преимущества списка инициализации:
— Переменная всегда инициализирована, нет возможности использовать неинициализированную переменную.
— Компилятор может выполнить оптимизации, т. к. знает значение переменной при инициализации.
— При инициализации классов вызываются нужные конструкторы.
— Код становится более читабельным, инициализация видна сразу при объявлении.