#вопросы_с_собеседований
Что такое aliasing?
Aliasing - это ситуация, когда две или более переменные ссылаются на одну и ту же область памяти. Это может привести к непредсказуемому поведению программы, так как изменение одной переменной повлияет на другую.
Примеры ситуаций, которые могут вызывать aliasing:
- Использование указателей или ссылок, указывающих на один и тот же объект.
- Передача одного и того же объекта в функцию по значению и по ссылке.
- Возврат ссылки или указателя из функции на локальный объект.
- Использование union для хранения разных типов данных.
Чтобы избежать проблем с aliasing, нужно следить за жизненным циклом объектов и не допускать ситуаций, когда два указателя указывают на одну область памяти после того, как один из объектов был уничтожен. Также полезно использовать const когда это возможно, чтобы явно указывать, что данные не должны изменяться.
Что такое aliasing?
Примеры ситуаций, которые могут вызывать aliasing:
- Использование указателей или ссылок, указывающих на один и тот же объект.
- Передача одного и того же объекта в функцию по значению и по ссылке.
- Возврат ссылки или указателя из функции на локальный объект.
- Использование union для хранения разных типов данных.
Чтобы избежать проблем с aliasing, нужно следить за жизненным циклом объектов и не допускать ситуаций, когда два указателя указывают на одну область памяти после того, как один из объектов был уничтожен. Также полезно использовать const когда это возможно, чтобы явно указывать, что данные не должны изменяться.
RCU (Read-Copy-Update)
RCU (Read-Copy-Update) - это механизм синхронизации доступа к данным в многопоточных приложениях.
Он позволяет избежать блокировок при чтении данных, делая копию для чтения и обновляя оригинал после того, как все чтения завершены.
RCU особенно полезен, когда чтение данных происходит гораздо чаще, чем запись.
В примере мы сначала берем rcu_read_lock, чтобы защитить чтение foo. В другом потоке происходит модификация foo с помощью rcu_assign_pointer, которая делает копию данных, а оригинал удаляется после synchronize_rcu.
Таким образом чтение в первом потоке происходит без блокировок и избегает конфликтов с изменением данных в другом потоке. RCU гарантирует, что указатель foo будет виден как старое значение в первом потоке.
RCU (Read-Copy-Update) - это механизм синхронизации доступа к данным в многопоточных приложениях.
Он позволяет избежать блокировок при чтении данных, делая копию для чтения и обновляя оригинал после того, как все чтения завершены.
RCU особенно полезен, когда чтение данных происходит гораздо чаще, чем запись.
В примере мы сначала берем rcu_read_lock, чтобы защитить чтение foo. В другом потоке происходит модификация foo с помощью rcu_assign_pointer, которая делает копию данных, а оригинал удаляется после synchronize_rcu.
Таким образом чтение в первом потоке происходит без блокировок и избегает конфликтов с изменением данных в другом потоке. RCU гарантирует, что указатель foo будет виден как старое значение в первом потоке.
Libpq
Libpq - это библиотека, которая предоставляет API для взаимодействия с СУБД PostgreSQL из приложений на С++.
Она используется, когда нужно подключиться к базе данных PostgreSQL и выполнять SQL-запросы из кода на C++.
Этот код подключается к БД PostgreSQL, выполняет запрос к таблице employees и выводит количество строк и столбцов в результате.
Libpq - это библиотека, которая предоставляет API для взаимодействия с СУБД PostgreSQL из приложений на С++.
Она используется, когда нужно подключиться к базе данных PostgreSQL и выполнять SQL-запросы из кода на C++.
Этот код подключается к БД PostgreSQL, выполняет запрос к таблице employees и выводит количество строк и столбцов в результате.
#вопросы_с_собеседований
Что такое функторы?
Функторы - это объекты классов, которые могут вызываться как функции.
Другими словами, функторы позволяют обращаться к объекту так, как если бы это была обычная функция.
Функторы полезны в следующих ситуациях:
- Позволяют инкапсулировать функциональность в классе, связывать ее с состоянием объекта.
- Дают возможность передавать объекты-функторы в функции и хранить их в структурах данных.
- Упрощают написание обобщенных алгоритмов, которым нужно выполнять некоторую функциональность, не завися от конкретных типов объектов.
- Используются в стандартной библиотеке C++, например при работе с потоками, для запуска функций в потоке.
Что такое функторы?
Другими словами, функторы позволяют обращаться к объекту так, как если бы это была обычная функция.
Функторы полезны в следующих ситуациях:
- Позволяют инкапсулировать функциональность в классе, связывать ее с состоянием объекта.
- Дают возможность передавать объекты-функторы в функции и хранить их в структурах данных.
- Упрощают написание обобщенных алгоритмов, которым нужно выполнять некоторую функциональность, не завися от конкретных типов объектов.
- Используются в стандартной библиотеке C++, например при работе с потоками, для запуска функций в потоке.
for-each циклы
Цикл for-each - это удобный способ перебрать все элементы контейнера (массива, вектора и т. д.). Синтаксис:
for (type element : container) {
// тело цикла
}
Цикл последовательно проходит по всем элементам контейнера и записывает каждый в переменную element.
#это_база
Цикл for-each - это удобный способ перебрать все элементы контейнера (массива, вектора и т. д.). Синтаксис:
for (type element : container) {
// тело цикла
}
Цикл последовательно проходит по всем элементам контейнера и записывает каждый в переменную element.
#это_база
set::erase()
Функция set::erase() используется для удаления элементов из контейнера set.
set::erase() принимает значение, которое нужно удалить, в качестве аргумента и удаляет из set все элементы, эквивалентные переданному значению.
Если такого значения нет в set, не делает ничего.
В этом примере создается set целых чисел, добавляются значения от 1 до 5. Затем вызывается numbers.erase(3) - это удалит элемент со значением 3 из set.
#это_база
Функция set::erase() используется для удаления элементов из контейнера set.
set::erase() принимает значение, которое нужно удалить, в качестве аргумента и удаляет из set все элементы, эквивалентные переданному значению.
Если такого значения нет в set, не делает ничего.
В этом примере создается set целых чисел, добавляются значения от 1 до 5. Затем вызывается numbers.erase(3) - это удалит элемент со значением 3 из set.
#это_база
#вопросы_с_собеседований
Как и для чего используется метапрограммирование шаблонов?
Метапрограммирование шаблонов используется для генерации кода программы на этапе компиляции.
Это позволяет создавать высокооптимизированные гибкие библиотеки, которые адаптируются под конкретные типы во время компиляции за счет метапрограммирования шаблонов.
Основные способы метапрограммирования шаблонов:
- Шаблонные метапрограммы.
- Концепции.
- Типовые списки.
- constexpr if.
- Шаблонные рекурсивные алгоритмы.
Как и для чего используется метапрограммирование шаблонов?
Это позволяет создавать высокооптимизированные гибкие библиотеки, которые адаптируются под конкретные типы во время компиляции за счет метапрограммирования шаблонов.
Основные способы метапрограммирования шаблонов:
- Шаблонные метапрограммы.
- Концепции.
- Типовые списки.
- constexpr if.
- Шаблонные рекурсивные алгоритмы.
#вопросы_с_собеседований
Каковы спецификаторы доступа в C++?
Спецификаторы доступа позволяют инкапсулировать данные класса и ограничивать интерфейс взаимодействия с объектами.
Это важный инструмент ООП для сокрытия внутренней реализации и предоставления только необходимого уровня доступа извне.
В C++ определены следующие спецификаторы доступа:
public - объявленные таким образом данные и методы класса доступны из любого места программы.
protected - защищенные данные и методы доступны только из самого класса и его подклассов.
private - закрытые элементы доступны только из тела самого класса, где они определены.
Кроме того, есть спецификатор default - когда явный спецификатор доступа не указан. Такие элементы доступны только из текущего класса и друзей.
Каковы спецификаторы доступа в C++?
Это важный инструмент ООП для сокрытия внутренней реализации и предоставления только необходимого уровня доступа извне.
В C++ определены следующие спецификаторы доступа:
public - объявленные таким образом данные и методы класса доступны из любого места программы.
protected - защищенные данные и методы доступны только из самого класса и его подклассов.
private - закрытые элементы доступны только из тела самого класса, где они определены.
Кроме того, есть спецификатор default - когда явный спецификатор доступа не указан. Такие элементы доступны только из текущего класса и друзей.
std::pair
std::pair - это шаблон класса из стандартной библиотеки, который инкапсулирует пару значений разных типов.
Он часто используется для возврата нескольких значений из функции.
В этом примере getStats возвращает пару значений - сумму и среднее элементов массива. С помощью std::pair эти значения упаковываются в один возвращаемый объект. В main используется structured binding для распаковки пары в переменные sum и avg.
std::pair - это шаблон класса из стандартной библиотеки, который инкапсулирует пару значений разных типов.
Он часто используется для возврата нескольких значений из функции.
В этом примере getStats возвращает пару значений - сумму и среднее элементов массива. С помощью std::pair эти значения упаковываются в один возвращаемый объект. В main используется structured binding для распаковки пары в переменные sum и avg.
nullptr
nullptr - это ключевое слово, которое используется для обозначения null-указателя (указателя, который не ссылается ни на какой объект).
Основные моменты, которые нужно знать о nullptr:
- nullptr предпочтительнее использовать вместо старого способа обозначения null-указателя - константы 0 или NULL.
- nullptr гарантированно преобразуется в любой тип указателя.
- Использование nullptr позволяет избежать ошибок по сравнению с константами вроде NULL и делает код более читабельным.
В примере мы проверяем указатель ptr на равенство nullptr.
#это_база
nullptr - это ключевое слово, которое используется для обозначения null-указателя (указателя, который не ссылается ни на какой объект).
Основные моменты, которые нужно знать о nullptr:
- nullptr предпочтительнее использовать вместо старого способа обозначения null-указателя - константы 0 или NULL.
- nullptr гарантированно преобразуется в любой тип указателя.
- Использование nullptr позволяет избежать ошибок по сравнению с константами вроде NULL и делает код более читабельным.
В примере мы проверяем указатель ptr на равенство nullptr.
#это_база
std::begin() и std::end()
Функции std::begin() и std::end() из заголовочного файла <iterator> используются для получения итераторов на начало и конец контейнера соответственно.
Это часто нужно при работе с алгоритмами STL.
В примере std::begin() вернёт итератор на первый элемент контейнера, а std::end() - на позицию за последним элементом.
Эти функции работают со всеми стандартными контейнерами (vector, list, array и т.д.) и позволяют универсально перебирать их элементы.
Функции std::begin() и std::end() из заголовочного файла <iterator> используются для получения итераторов на начало и конец контейнера соответственно.
Это часто нужно при работе с алгоритмами STL.
В примере std::begin() вернёт итератор на первый элемент контейнера, а std::end() - на позицию за последним элементом.
Эти функции работают со всеми стандартными контейнерами (vector, list, array и т.д.) и позволяют универсально перебирать их элементы.
#вопросы_с_собеседований
В чем разница между ссылочными переменными и указателями?
Ссылка - это псевдоним объекта, альтернативное имя уже существующего объекта.
Указатель - переменная, хранящая адрес другой переменной.
Ссылка должна инициализироваться при объявлении и не может иметь нулевое значение, в отличие от указателя, способного иметь значение NULL.
Ссылка не может быть переприсвоена другому объекту после инициализации.
Указатель можно перенаправить на другой объект.
Ссылка не хранит адрес объекта, она просто становится еще одним именем объекта.
Указатель явно хранит адрес в памяти.
Ссылка всегда должна ссылаться на валидный объект.
Указатель может висеть в воздухе.
В чем разница между ссылочными переменными и указателями?
Ссылка должна инициализироваться при объявлении и не может иметь нулевое значение, в отличие от указателя, способного иметь значение NULL.
Ссылка не может быть переприсвоена другому объекту после инициализации.
Указатель можно перенаправить на другой объект.
Ссылка не хранит адрес объекта, она просто становится еще одним именем объекта.
Указатель явно хранит адрес в памяти.
Ссылка всегда должна ссылаться на валидный объект.
Указатель может висеть в воздухе.
Кортежи
Кортежи - это шаблонный контейнерный тип данных, позволяющий хранить набор элементов разных типов.
Доступ к элементам осуществляется по индексу через std::get, а типы элементов должны быть указаны при объявлении кортежа.
Кортежи удобно использовать для возврата нескольких значений из функции.
#это_база
Кортежи - это шаблонный контейнерный тип данных, позволяющий хранить набор элементов разных типов.
Доступ к элементам осуществляется по индексу через std::get, а типы элементов должны быть указаны при объявлении кортежа.
Кортежи удобно использовать для возврата нескольких значений из функции.
#это_база
#вопросы_с_собеседований
Что такое структуры и чем они отличаются от классов?
- Структуры по умолчанию имеют публичный доступ к полям, а в классах - приватный.
- Структуры копируются целиком при присваивании и передаче в функцию, классы - по ссылке.
- В структурах нет конструкторов по умолчанию, а в классах есть.
- Структуры чаще используются для простых данных, а классы - когда нужно более сложное поведение.
- Структуры не поддерживают наследование, в отличие от классов.
- Структуры можно создавать на стеке без оператора new, объекты класса только динамически.
Структуры эффективнее для маленьких объектов, классы дают больше гибкости и функционала за счет наследования и инкапсуляции.
Что такое структуры и чем они отличаются от классов?
- Структуры копируются целиком при присваивании и передаче в функцию, классы - по ссылке.
- В структурах нет конструкторов по умолчанию, а в классах есть.
- Структуры чаще используются для простых данных, а классы - когда нужно более сложное поведение.
- Структуры не поддерживают наследование, в отличие от классов.
- Структуры можно создавать на стеке без оператора new, объекты класса только динамически.
Структуры эффективнее для маленьких объектов, классы дают больше гибкости и функционала за счет наследования и инкапсуляции.
new или malloc()?
Рекомендуется использовать оператор new вместо функции malloc из Си, так как new обеспечивает дополнительную функциональность и безопасность:
- new автоматически вызывает конструктор объекта, malloc - нет.
- new возвращает типизированный указатель, malloc - void*.
- new выбрасывает исключение при ошибке, malloc - возвращает NULL.
- объекты, созданные через new, автоматически уничтожаются при удалении, malloc - нет.
Рекомендуется использовать оператор new вместо функции malloc из Си, так как new обеспечивает дополнительную функциональность и безопасность:
- new автоматически вызывает конструктор объекта, malloc - нет.
- new возвращает типизированный указатель, malloc - void*.
- new выбрасывает исключение при ошибке, malloc - возвращает NULL.
- объекты, созданные через new, автоматически уничтожаются при удалении, malloc - нет.
Ключевое слово this
this используется для ссылки на текущий объект класса. Это слово инициализируется при создании объекта и доступно во всех методах объекта.
В примере в методе getArea() используется this для доступа к переменным width и height текущего объекта rect.
Результат работы программы:
Площадь: 12
#это_база
this используется для ссылки на текущий объект класса. Это слово инициализируется при создании объекта и доступно во всех методах объекта.
В примере в методе getArea() используется this для доступа к переменным width и height текущего объекта rect.
Результат работы программы:
Площадь: 12
#это_база
#вопросы_с_собеседований
Для чего нужен был тип std::auto_ptr<T>?
Тип std::auto_ptr<T> использовался для автоматического управления памятью и представляет собой умный указатель на объект типа T.
auto_ptr упрощает управление памятью и исключает утечки памяти из-за забытого вызова delete. Однако в современном C++ auto_ptr считается устаревшим и заменен на std::unique_ptr.
Для чего нужен был тип std::auto_ptr<T>?
auto_ptr упрощает управление памятью и исключает утечки памяти из-за забытого вызова delete. Однако в современном C++ auto_ptr считается устаревшим и заменен на std::unique_ptr.
Умные указатели в С++
Умные указатели - это шаблоны классов, которые позволяют автоматически управлять памятью и не допускать утечек.
Среди основных умных указателей:
- unique_ptr - указатель, который владеет объектом в единственном экземпляре.
- shared_ptr - указатель, у которого может быть несколько владельцев.
- weak_ptr - указатель на объект, владельцем которого является shared_ptr.
#это_база
Умные указатели - это шаблоны классов, которые позволяют автоматически управлять памятью и не допускать утечек.
Среди основных умных указателей:
- unique_ptr - указатель, который владеет объектом в единственном экземпляре.
- shared_ptr - указатель, у которого может быть несколько владельцев.
- weak_ptr - указатель на объект, владельцем которого является shared_ptr.
#это_база
#вопросы_с_собеседований
В каком порядке инициализируются и уничтожаются члены класса?
Сначала вызываются конструкторы базовых классов в порядке наследования.
Затем инициализируются члены класса в порядке их объявления в классе.
После этого вызывается конструктор текущего класса.
Аналогичным образом происходит уничтожение объекта:
Сначала вызывается деструктор текущего класса.
Затем уничтожаются члены класса в порядке, обратном их инициализации.
Далее вызываются деструкторы базовых классов в обратном порядке наследования.
В каком порядке инициализируются и уничтожаются члены класса?
Затем инициализируются члены класса в порядке их объявления в классе.
После этого вызывается конструктор текущего класса.
Аналогичным образом происходит уничтожение объекта:
Сначала вызывается деструктор текущего класса.
Затем уничтожаются члены класса в порядке, обратном их инициализации.
Далее вызываются деструкторы базовых классов в обратном порядке наследования.
std::find
std::find - это алгоритм из стандартной библиотеки, который ищет элемент в контейнере.
Он принимает 3 аргумента:
- Итератор на начало контейнера
- Итератор на конец контейнера
- Искомое значение
И возвращает итератор на найденный элемент или итератор на конец, если элемент не найден.
В примере мы ищем элемент со значением 3 в векторе vec. std::find возвращает итератор на найденный элемент, по которому мы выводим значение.
std::find - это алгоритм из стандартной библиотеки, который ищет элемент в контейнере.
Он принимает 3 аргумента:
- Итератор на начало контейнера
- Итератор на конец контейнера
- Искомое значение
И возвращает итератор на найденный элемент или итератор на конец, если элемент не найден.
В примере мы ищем элемент со значением 3 в векторе vec. std::find возвращает итератор на найденный элемент, по которому мы выводим значение.