Какие бывают типы конструкторов в C++
Что проверяют
Не список названий, а понимание, какие конструкторы компилятор создаёт сам, когда перестаёт это делать и как это связано с владением ресурсами. Следом спрашивают правило трёх и пяти и зачем перемещению noexcept.
Как отвечать
Перечислите виды с назначением:
- по умолчанию: без аргументов или со всеми аргументами по умолчанию. Неявно генерируется, только если не объявлен ни один другой конструктор;
- с параметрами: с одним аргументом и без
explicitэто ещё и конструктор преобразования, иf(42)дляvoid f(Widget)неожиданно скомпилируется; - копирования:
T(const T&). Неявный копирует члены поэлементно и ломается на сырых владеющих указателях; - перемещения (C++11):
T(T&&) noexcept, забирает ресурсы у временного объекта; - делегирующий (C++11): вызывает другой конструктор того же класса;
- наследующий (C++11):
using Base::Base;подтягивает конструкторы базового класса; - с
std::initializer_list: выигрывает перегрузку при фигурных скобках, поэтомуstd::vector<int> v{10, 1}это два элемента, аv(10, 1)десять единиц.
Дальше правила генерации. Объявили деструктор или копирующие операции, и неявный конструктор перемещения не создаётся, перемещение молча становится копированием. Объявили перемещающие операции, и неявное копирование удалено. Отсюда правило пяти и более практичное правило нуля: владение отдайте std::unique_ptr или std::vector, и специальные члены писать не придётся. = default и = delete делают намерение явным. С C++17 пропуск копирования для prvalue гарантирован.
Про шаблоны: шаблонный конструктор никогда не считается конструктором копирования, неявный копирующий всё равно сгенерируется.
Где спотыкаются
Забывают noexcept у перемещения. std::vector при реаллокации идёт через std::move_if_noexcept и в этом случае копирует элементы.
Думают, что члены инициализируются в порядке списка инициализации. На деле в порядке объявления в классе, и член, зависящий от ещё не созданного соседа, читает мусор.
Вызывают виртуальную функцию из конструктора базы и ждут версию наследника. Динамический тип в этот момент ещё базовый.