C++ 1MIT весна 1 2020 — билеты

Материал из CSC Wiki
Перейти к:навигация, поиск

Общее

Цель экзамена — проверить, что студент знает основную теорию по C++, а за час смог разобраться и осознать много деталей по определённой теме так, чтобы рассказать их.

Основная теория — то, что необходимо знать работающему на C++ программисту, когда он встречается с непонятным кодом или непонятной задачей, чтобы знать, куда гуглить или думать.

Формат

  • На подготовку — час (60 минут или больше, если возникает очередь)
    • Можно пользоваться любыми существующими до начала экзамена (не просто до начала подготовки) материалами, бумажными материалами.
    • Можно гуглить что угодно
    • Можно запускать компилятор, локальную среду разработки или редактор текст
    • Нельзя пользоваться онлайн-компиляторами и средами вроде ideone, wandbox, Google Docs (чтобы не было проблем с тем, что вы случайно что-то пошарили)
    • Нельзя добавлять ничего в интернет
    • Нельзя общаться с кем угодно, кроме принимающих: с друзьями и врагами, задавать вопросы в чатах, на форумах, StackOverflow, твитить, менять статус в ВК и ICQ
    • Рекомендуется во время подготовки отрепетировать свой ответ.
  • На ответ — полчаса (30 минут)
    • Это жёсткое ограничение: через 30 минут принимающий не может задавать вам вопросы и должен поставить оценку. Нельзя "уйти подумать". Это чтобы все успели ответить за один день и не надо было подробно следить за каждым компьютером.
    • Предполагается, что за ~15 минут вы рассказали билет и ещё 15 минут есть на вопросы и обсуждение деталей.
    • От вас на твёрдую "5/5" требуется идеальный устный ответ билета и ответы на вопросы по теме билета. Текст можете писать только для себя, но можно и показывать принимающему и комментировать. Например, так полезно с кодом.
    • Что проверяется: на "5/5" вы за час смогли вспомнить, осознать и рассказать детали из вашего вопроса (возможно, с помощью материалов).
    • Также могут бегло спросить любые связные темы, и совсем бегло и поверхностно — любые темы вообще. В том числе из первого семестра. Принимающий руководствуется своим здравым смыслом: "что надо точно знать для понимания билета" и "что обязательно должен знать программист на C++".
    • Можно пользоваться тем же, чем и при подготовке. В частности, гуглить. Однако это может влиять на оценку и доп. вопросы: если вы зачитали определение с экрана и показали заготовленные примеры, то вас попросят поменять пример и сразу рассказать, что в нём теперь происходит.
  • Ставится оценка от 2 до 5 включительно, целая.

Инструкция для студентов

  1. Запишитесь в табличку.
  2. 06.06.2020 (сб) в 19:30 МСК перепроверьте своё время начала подготвоки.
  3. Подготовьте Zoom и рабочее место:
    1. Установите в Zoom в качестве имени Имя Фамилия кириллицей ровно в таком порядке.
    2. Отключите любые фоны, искажения звука, отключите второй монитор.
    3. Уберите со стола ноутбуки, смартфоны, Алису и прочую электронику.
    4. Проверьте, что у вас последняя версия Zoom.
    5. Проверьте, что у вас в Zoom работают с одного и того же устройства: камера, микрофон, показ всего рабочего стола (не отдельного окна!).
    6. Проверьте, что вы можете своей веб-камерой показать весь стол и пространство вокруг себя (хоть ноут повернуть, хоть веб-камеру снимать).
    7. Обеспечьте отсутствие других людей и животных в зоне, где вы отвечаете.
    8. Поставьте в настройках записи галочки: "Record a separate audio file for each participant who speaks", "Record video during screen sharing" и (только если есть) "Place video next to the shared screen in the recording".
  4. 07.06.2020 за десять минут до времени подготовки:
    1. Отключите все мессенджеры, включая Telegram. Закройте все вкладки с соцсетями.
    2. Уберите мобильный телефон со стола и из карманов.
    3. Войдите по Zoom-ссылке на экзамен. Хост встречи вас впустит, если у вас корректное имя. Если не пускают дольше пяти минут — напишите текущему хосту (по умолчанию — Егор, но следите за анонсами в официальном чате).
    4. Включите микрофон с хорошей громкостью и веб-камеру. Не отключайте их на протяжении всего экзамена. Если вас отвлекает шум — можете выключить у себя звук.
    5. Сделайте "Pin video" на своё видео
    6. Включите локальную запись. Не выключайте её весь экзамен. Вас могут попросить её предоставить.
  5. Во время подготовки с хостом переписывайтесь, не говорите, чтобы не отвлекать коллег.
  6. Перед началом подготовки:
    1. После письменной просьбы хоста в чате покажите свой стол. Если вас что-то попросят убрать — уберите.
    2. Хост напишет вам номер билета в чате. Убедитесь, что вы пользуетесь последней официальной версией билетов на этой странице.
  7. Во время подготовки вы обязаны следить за чатом в Zoom — там могут появляться важные уведомления и/или просьбы хоста.
  8. Если вы готовы отвечать — напишите хосту, в ближайшее время вам назначат проверяющего и переведут в отдельную Breakout room с проверяющим. Через час подготовки вы можете быть автоматически переведены в комнату с принимающим. Если все проверяющие заняты — бонусное время для подготовки.
  9. В начале ответа
    1. Пошарьте экран целиком и не отключайте до окончания ответа. Даже если вам не надо ничего показывать на экране.
    2. Убедитесь, что идёт локальная запись.
  10. Расскажите билет примерно за 15 минут, чтобы оставить ещё 15 минут на вопросы принимающего.
  11. После конца ответа покиньте встречу с экзаменом.
  12. Сохраните локальную запись. Хотя бы до 7 июля.

Если что-то идёт не так

  1. Вы можете позвать хоста из breakout room (ask for help)
  2. Вы можете написать хосту в личку в главной комнате
  3. Если отвалился интернет или запись — перезаходите, включайте запись, вас отправят обратно к тому же принимающему
  4. Если всё совсем плохо — можете написать в Telegram хосту

Обязательные знания

На экзамене требуется знать все понятия ниже без подготовки, а также уметь приводить примеры к ним. Иначе — блокирующий "неуд".

  1. Переменные
    • статическая типизация
    • тип переменной
    • размер переменной, размер типа
    • типы int, char: типичные размеры. Например, на архитектуре x86_64 под Linux в компиляторе GCC.
  2. Основные конструкции языков C и C++
    • объявления переменных
    • выражения и операторы:
      • арифметические (+, -, *, /, %, +=, -=, *=, /=, %=, ++, --)
      • булевы (<, <=, >, >=, ==, !=, &&, ||, !)
      • на минимальную оценку необязательно знать: отличия постфиксных и префиксных операторов
    • условный оператор if
    • циклы for, while
  3. Функции
    • объявление и определение функции, требуется отличать между собой (можно случайно перепутать, но после вопроса исправиться)
    • вызов функции (синтаксис, не нужно знать mangling, конвенции вызовов)
    • возвращаемое значение
    • рекурсивный вызов
  4. Основные конструкции C++
    • синтаксис static_cast
    • синтаксис объявления пространств имён, обращения к элементу внутри пространства имён
    • auto для объявления переменных
    • range-based for, в том числе с auto& и const auto&
    • использование unique_ptr и make_unique для владения объектом вместо чистых указателей
    • синтаксис шаблонов, достаточный для написания минимального адаптера stack<T> поверх deque
  5. Классы
    • определение класса, конструктор, деструктор, методы
    • специальные методы (пять штук), правило нуля, правило пяти
    • приватные/публичные поля и методы
    • наследование: базовый синтаксис
  6. Полиморфные классы
    • виртуальные методы и их отличия от невиртуальных
    • необходимость виртуального деструктора
    • slicing (срезка объектов) при присваивании полиморфного класса в переменную типа "базовый класс", как защититься (хранить только ссылки/умные указатели)
  7. Const correctness
    • синтаксис константных ссылок, применение при передаче аргументов
    • невозможность изменять константные объекты и их поля
    • const-qualifier у методов (const member function), перегрузка по const-qualifier (const overloading)
  8. Использование move-семантики
    • эффективная инициализация полей класса из аргументов, принятых по значению или по rvalue-ссылке
    • moved-from состояние у объектов: может быть не определено, может быть невозможно обнаружить, пример ошибки
    • отсутствие необходимости move из результата функции, возвращённого по значению
    • необходимость move для явной передачи владения unique_ptr
  9. STL
    • использование vector как динамического массива фиксированной длины, push_back и emplace_back
    • использование map со стандартным компаратором, особенность operator[] (создаёт значение даже при чтении)
  10. Исключения
    • синтаксис try/catch, необходимость ловить по константной ссылке (см. slicing)
    • stack unwinding
    • базовая гарантия исключений: что такое, как обеспечить (умные указатели, правило нуля)

Билеты

Общее

Один билет — один вопрос.

Также указаны номера лекций, где можно смотреть темы. Можно смотреть записи, можно смотреть presentation.md (при наличии) или plan.md (менее приоритетно) в репозитории github.com/yeputons/hse-2019-cpp

Термины

Инвариантность/ковариантность — разные способы добавлять наследование между Foo<Base> и Foo<Derived>, можно посмотреть первые четыре картинки в статье. Контравариантность нам не нужна.

Nothrow/noexcept — синонимы. Когда мы хотим сказать "гарантий нет", то говорим "гарантий нет" или "no exception safety".

Ответ

Предполагается, что Егор может рассказать любой билет за 10-15 минут. Не требуется устраивать полноценную последовательную лекцию, лучше для экономии времени показать один сложный пример. Деталей надо раза в два меньше, чем на лекциях.

Приводить "содержательные" примеры необязательно, однако на каждую фишку языка могут спросить: "а зачем оно надо?"

Для всех элементов стандартной библиотеки из std:: требуется рассказать не только синтаксис и применение, но и как они могут быть реализованы через более примитивные операции/функции. Например, std::move и std::forward — это static_cast определённого вида, а std::ifstream может быть обёрткой над Сишным FILE*.

Вопросы

Финализировано 05.06.2020 19:14 МСК.

  1. Детали классов
    • 26-200421
    • Корректное объявление глобальные констант и статических констант-членов
    • Перегрузка operator-> (30-200526)
    • Функции-друзья и friend class (30-200526)
    • using Foo::A для методов и полей: method hiding, изменение видимости (16-200128),использование для упрощения конструкторов (25-200414)
  2. Пространства имён (namespaces)
    • 14-200114
    • Вложенные пространства имён, способы объявления
    • Возможность переоткрыть пространство имён (классы так не умеют)
    • Анонимное пространство имён (namespace {}) для internal linkage
    • typedef и using A = B
    • using Foo::A для произвольных символов (переменные, функции, любые типы, шаблоны)
    • using namespace
  3. Правила поиска имён (глобальных и внутри классов)
    • 14-200114
    • Где возникает qualified lookup, а где — unqualified
    • Явное обращение к глобальному пространству имён (::foo)
    • Правила unqualified lookup в телах функций, методов, на уровне пространств имён ("глобально").
    • Forward declaration для функций и классов, особенности неполных типов (15-200121)
  4. Argument-dependent-lookup (ADL)
    • 26-200421
    • Применение: вызов операторов, свободные функции как часть интерфейса класса (но без доступа к приватным полям)
    • Алгоритм работы: включение-выключение, связанные с аргументами типы, выбор пространств имён и using
    • Как правильно использовать swap с using
    • Hidden friends
  5. Стандартная библиотека C++, основы ввода-вывода
    • 14-200114
    • Конвенции именований стандартной библиотеки, отличия stdio.h и cstdio
    • Иерархия потоков ввода-вывода: от std::ios до std::stringstream и std::fstream
    • Файловый ввод-вывод
    • Байтовый и текстовый режим (флаг binary)
    • Обработка ошибок (три бита, установка флагов)
    • Проверка конца файла и почему нельзя писать while (!eof)
  6. Стандартная библиотека C++, детали ввода-вывода
    • 14-200114
    • Конвенции именований стандартной библиотеки, отличия stdio.h и cstdio
    • Неформатированный ввод-вывод (get, peek, unget, read, seekg/tellg)
    • Форматированный ввод-вывод, отличия от printf (типобезопасность, поддержка пользовательских типов)
    • Реализация своих операторов ввода-вывода, включая обработку ошибок
    • 15-200121
    • Реализация своих манипуляторов (например, read_le_int32 или eat)
  7. Множественное наследование
    • 16-200128
    • Синтаксис, пример
    • Возможное представление в памяти, пример изменения адреса при static_cast (потому что начало подобъект теперь не всегда совпадает с началом объекта)
    • Порядок инициализации/уничтожения подобъектов и полей, как передать параметры конструкторам
    • Возможное дублирование базового класса и возникающие неоднозначности при приведении типа
  8. Виртуальное наследование
    • 16-200128
    • Виртуальный базовый класс: синтаксис, пример
    • Порядок инициализации/уничтожения подобъектов и полей, как и где передать параметры конструктором
    • Возможное представление в памяти (даже для неполиморфных классов)
    • Невозможность простого приведения типа от виртуальной базы к наследнику (30-200526,разбор теста)
    • Использование для интерфейсов (abstract base class, ABC)
    • Что происходит, если один класс объявляется и виртуальным, и невиртуальным
    • Взаимодействие с dynamic_cast (25-200414) при наличии виртуальных методов (работает) и их отсутствии (невозможно)
  9. Исключения — основы
    • 17-200204,18-200211
    • Предусловия и постусловия конструктора и деструктора, инвариант объекта
    • Как отличить "ошибки программирования" (undefined behavior, нарушение инвариантов, невозможно предсказать поведение после) и "ошибки окружения" (некорректный ввод пользователя, теоретически можно предсказать и обработать), разные стратегии обработки для двух видов ошибок
    • Примеры обработки разных видов ошибок без исключений: assert, коды возврата
    • Исключения: try, catch, throw (синтаксис, и для новых исключений, и для перебрасывания "текущего"), где что ставить для обработки ошибок
    • Вложенные try/catch, несколько catch подряд и почему важно ловить по ссылке
    • Stack unwinding (раскрутка стэка) и уничтожение локальных ресурсов
    • Идиома Resource Acquisition Is Initialization (RAII)
    • Примеры исключений из стандартной библиотеки (std::exception и его наследники, bad_alloc)
  10. Исключения — детали
    • 17-200204,18-200211
    • Исключения, вылетающие из конструктора (в том числе поля или базового класса), делегирующего конструктора (25-200414)
    • Исключения, вылетающие из деструктора, по умолчанию запрещены, причина
    • Function try block
    • Преимущества и недостатки исключений
    • Непойманные исключения
  11. Гарантии исключений
    • 17-200204
    • Определения и примеры nothrow, strong, basic, no guarantee
    • Невозможность обеспечения basic guarantee на основе no guarantee
    • Обеспечение базовой гарантии при помощи RAII
    • Подвохи с базовой гарантией при реализации operator=(const MyString&), если сделать подряд delete[] data; data = new char[...] (можно получить UB в деструкторе, чинить — сначала выделить, потом портить поля)
    • Особенности при написании шаблонных классов (надо очень аккуратно с гарантиями шаблонного параметра) (30-200526,разбор теста)
    • Спецификатор noexcept для функций и методов (тонкость: new всегда кидает bad_alloc)
    • Условный noexcept, оператор noexcept (27-200428)
  12. Обеспечение строгой гарантии исключений
    • 17-200204,19-200218
    • Конструкторы и деструкторы — это просто
    • Проведение операций в два шага
    • Copy-and-swap trick для упрощения строгой гарантии исключений
    • Семантические проблемы при реализации конструктора/оператора перемещения: примеры, когда можно решить и когда нельзя
    • Невозможность написать stack::pop() с возвратом значения (19-200218)
  13. Лямбда-функции и функторы
    • 18-200211,24-200407
    • Объект-функтор (с перегруженным operator()): применение, чем лучше функций
    • Использование в алгоритмах (23-200312)
    • Использование как компараторов в ассоциативных контейнерах (24-200407)
    • Лямбды: синтаксис, захват переменных и всей области по значению, по ссылке, копированием (C++14), захват this
    • Невозможность назвать тип лямбды, во что превращается лямбда, сохраняется возможность оптимизаций
    • Спецификатор mutable у лямбды и изменяемость захваченных значений
    • Автовывод и явное указание возвращаемого типа лямбды через []() -> Foo
    • Шаблонные лямбды: auto-параметр
    • Отличия std::function от лямбда-функций, эффективность вызовов и возможности для оптимизаций
  14. Шаблоны — основы
    • 18-200211
    • Шаблонные классы (параметр-тип, синтаксис), инвариантность (независимость) инстанциаций, раздувание скомпилированного кода и возможность оптимизаций
    • Проблемы с >> до C++11
    • В какой момент происходит инстанцирование класса, полей, методов, статических функций, отсутствие некоторых проверок компиляции до инстанцирования
    • Сохранение лямбда-функции в поле класса напрямую (параметризация класса типом лямбды)
    • Шаблонные функции: синтаксис определения и вызова с явным указанием параметров
    • Особенности при предоставлении гарантий исключений (надо очень аккуратно с гарантиями шаблонного параметра) 19-200218
    • Неявный конструктор присваивания и остальные (30-200526)
  15. Шаблоны — параметры
    • 18-200211
    • Параметры шаблонов: типы, значения, шаблоны, по умолчанию (19-200218)
    • Автовывод параметров шаблона из аргументов функции при вызове, параметры по умолчанию, можно указывать шаблонные параметры частично
    • 19-200218
    • Существование автовывода параметров шаблона из аргументов конструктора при вызове (class template argument deduction, CTAD, C++17)
    • 21-200303
    • Полные и частичные специализации шаблонов классов
  16. Шаблоны — детали
    • 19-200218
    • Псевдонимы шаблонов (typedef, template<typename T> using A = B вроде enable_if_t)
    • Шаблонные методы в шаблонных классах
    • Необходимость слов typename и template в некоторых контекстах, пример неоднозначности
    • 21-200303
    • Специализации шаблонов функций: существуют только полные, для псевдочастичных надо делать перегрузки (но так не всегда можно: std::swap можно по стандарту специализировать, но не перегружать)
    • Отличия специализации шаблонов функций и перегрузок (что идёт в явные шаблонные параметры)
  17. Вывод типов
    • 25-200414
    • В шаблонах, auto-переменных, возвращаемом значении функций и лямбд (также см. 30-200526)
    • Включая ссылки, указатели, константность, шаблоны, forwarding reference (29-200519)
    • Синтаксис auto foo() -> T для функций (30-200526)
  18. Приведения типов (casts)
    • 25-200414
    • Стандартные операторы приведения типов: неявное, static_cast, reinterpret_cast, const_cast, dynamic_cast, C-style-cast
    • Определение, когда применять и что "безопаснее"
    • Применение dynamic_cast для виртуального наследования (только если тип полиморфен, см. 30-200526,разбор теста)
  19. Пользовательские приведения типов (user-defined conversions)
    • 25-200414, 22-200310
    • Явные (explicit) и неявные (implicit) приведения типов
    • Оператор приведения типа, конструктор приведения
    • Модификатор explicit для конструкторов и операторов приведения
    • Особенности explicit operator bool() по сравнению с остальными explicit-операторами
  20. Ручное управление временем жизни объектов и массивов объектов
    • 19-200218
    • Placement new обязателен перед использованием объекта в куске памяти (reinterpret_cast не начинает жизнь), явный вызов деструктора
    • Для большинства объектов хватает (по выравниванию) выделить память через new char[]
    • aligned_alloc и free для объектов с большим требованием на выравнивание (25-200414)
    • Трудности с обработкой исключений при управлении массивом объектов, uninitialized_copy и схожие функции
    • Вспомогательный stack_impl для упрощения управления памятью с массивов объектов
  21. Move-семантика — использование
    • 20-200225,21-200303,разбор теста 28-200512
    • Решаемая проблема
    • Категории выражений: базовые (lvalue, xvalue, prvalue), комбинированные (glvalue, rvalue), как определить глазами категорию
    • Где происходит копирование/перемещение в зависимости от категории и куда пытаемся передать (в функцию, в конструктор, записать в отдельную переменную)
    • std::move для смены категории значения, реализация
    • Где можно/нужно/нельзя ставить std::move, примеры, в том числе unique_ptr
  22. Move-семантика для классов
    • 20-200225,21-200303,разбор теста 28-200512
    • Правило нуля
    • Ref-qualifier методов: для повышения корректности (stack().push(), lab_15 про Linq) и оптимизации (move из элемента вектора)
    • Типичная реализация конструктора, который инициализирует поля копированием из своих аргументов (лучше перемещением)
    • Rvalue-ссылки
    • Правила привязывания ссылок: lvalue, const lvalue, rvalue, бесполезность const rvalue
    • Move-конструктор, оператор перемещающего присваивания, гарантия исключений (хотим noexcept)
    • Правило пяти
  23. Оборачивание кода библиотечным
    • 29-200519
    • std::reference_wrapper, std::ref, std::cref
    • Perfect forwarding: reference collapsing, forwarding reference, std::forward
      • В том числе функторов (30-200526)
      • По умолчанию всю теорию можно не рассказывать, но надо подготовиться отвечать на вопросы
    • Отличия двух подходов
    • decltype(auto) для возвращаемого типа/переменной, корректность возврата void
  24. Стандартная библиотека — контейнеры
    • Конвенции именований стандартной библиотеки, отличия stdio.h и cstdio
    • 22-200310
    • Инвариантность контейнеров относительно типа
    • Виды контейнеров: последовательные, ассоциативные (упорядоченные и нет), адаптеры
    • Общие для контейнеров операции, гарантируемое стандартом время работы, noexcept гарантии
    • Удаление из контейнеров, инвалидация итераторов, range-based-for
  25. Стандартная библиотека — последовательные контейнеры
    • Конвенции именований стандартной библиотеки, отличия stdio.h и cstdio
    • 22-200311,23-200312
    • Основное свойство: элементы хранятся подряд в фиксированном пользователем порядке
    • Отличия, особенности, возможные реализации, как выбирать: array, list, string, vector, deque
    • Когда инвалидируются итераторы (в том числе end()), ссылки на элементы
    • Встроенные в list алгоритмы
    • Особенности vector<bool>
  26. Стандартная библиотека — ассоциативные (упорядоченные и нет) контейнеры
    • Конвенции именований стандартной библиотеки, отличия stdio.h и cstdio
    • 24-200407
    • Основное свойство для упорядоченных (элементы отсортированы по <) и неупорядоченных (хэш-таблица)
    • Отличия, особенности, возможные реализации, как выбирать
    • Когда инвалидируются итераторы (в том числе end()), ссылки на элементы
    • Свои компараторы, в том числе лямбда-функции
    • Подсказки для вставки
    • Удаление по значению, по итератору
    • Для *map*: особенности operator[] (и когда лучше contains, время работы), value_type
  27. Стандартная библиотека — адаптеры и bitset
    • Конвенции именований стандартной библиотеки, отличия stdio.h и cstdio
    • 24-200407
    • Основное свойство: построены на основе других контейнеров
    • Откуда берутся гарантии, инвалидация.
    • stack
    • queue
    • priority_queue
    • bitset
  28. Стандартная библиотека — итераторы
    • Конвенции именований стандартной библиотеки, отличия stdio.h и cstdio
    • 22-200310
    • Константные и неконстантные итераторы
    • Базовые операции с итераторами, время работы
    • Инвалидация итераторов
    • Иерархия итераторов (legacy, устаревшая, до C++17): input, output, forward, bidirectional, random, допустимые операции
    • Алгоритмы с итераторами
    • Range-based-for, std::begin, std::end, связь с ADL
    • Адаптеры итераторов: std::reverse_iterator
  29. Стандартная библиотека — алгоритмы
    • Конвенции именований стандартной библиотеки, отличия stdio.h и cstdio
    • 23-200312
    • Конвенции сравнения элементов: == и <
    • Примеры немодифицирующих, сравнивающих, модифицирующих алгоритмов
    • Erase-remove idiom, встроенный метод для list, своя реализация remove_if
    • Двоичный поиск: отличия lower_bound и upper_bound
    • Особенности использования двоичного поиска для не-RandomAccess итераторов, в том числе для set
  30. Стратегии хранения и владения объектами, невладеющие span/string_view, unique_ptr
    • 24-200407,25-200414,26-200421
    • Как передавать параметры в функции и возвращать значения: по значению, разным ссылкам, умным указателям
    • Особенности умных указателей для массивов (new[] и new)
    • string_view, span, когда использовать
    • unique_ptr для единоличного владения
    • Необходимость make_unique
  31. Стратегии хранения и владения объектами, shared_ptr
    • 24-200407,25-200414,26-200421
    • Как передавать параметры в функции и возвращать значения: по значению, разным ссылкам, умным указателям
    • Особенности умных указателей для массивов (new[] и new)
    • shared_ptr и weak_ptr для кэша
    • Необходимость make_shared
    • Ковариантность shared_ptr: преобразуется, как обычные указатели (к базовому неявно, к наследникам явно)
  32. Виды инициализации
    • 25-200414
    • The most vexing parse
    • Direct, copy, list инициализация: когда какая вызывается
    • Отличия default и value инициализации, как избегать default initialization
    • Агрегатные типы
    • initializer_list, в том числе рекурсивный
    • List initialization: отсутствие типа у braced-init-list, запрет сужающих приведений типов, инициализация агрегатов и initializer_list
  33. Кортежи
    • 26-200421
    • std::tuple, std::get, std::tuple_size, std::tuple_element, std::make_tuple
    • Ссылки внутри std::tuple
    • std::tie до C++11
    • Structured binding: синтаксис, как работает с массивами, кортежеподобными структурами (ADL), простыми структурами
  34. Базовое метапрограммирование
    • 21-200303 (vector<bool>)
    • Прокси-объекты: проблема (например, в vector<bool>), реализация
    • Проблема у прокси-объектов с auto, в том числе в range-based-for, хорошего решения нет
    • 23-200312
    • Tag dispatching для реализации эффективных алгоритмов для всех видов итераторов
    • Наследование тэгов
  35. Вычисления на этапе компиляции — основы
    • 27-200428
    • constexpr-вычисления, в том числе строк: константы, функции
    • Функции из типов в типы или значения (через шаблоны классов и их специализации), конвенции _t и _v
    • Реализация функций из типов куда угодно: наследование классов для упрощения кода, pattern matching для разбора типов
    • Примеры type traits для реализации своих алгоритмов (21-200303)
    • Стандартные классы integral_constant и его наследники
  36. Вычисления на этапе компиляции — детали
    • 27-200428
    • Свои расширяемые type traits (вроде FormatHelper из lab_18)
    • Невычислимые контексты: два вида decltype, sizeof, noexcept
    • Вспомогательная функция declval, пример внутри decltype
    • 28-200512
    • if constexpr
    • static_assert
    • std::conditional и реализация
  37. Хитрые указатели
    • 27-200428
    • std::addressof
    • Тип "функция" и "указатель на функцию"
    • Как взять указатель на перегруженную функцию и static_cast
    • Указатель на поле класса, на метод класса, синтаксис вызова (.* и ->*)
  38. SFINAE
    • 28-200512
    • Определение, исходное применение, отличие от hard compilation error, (не)работа внутри псевдонимов типов
    • Удаление перегрузок шаблонных функций, конструкторов, специализаций шаблонных классов в зависимости от корректности выражения:
      • Возвращаемый тип: явно, через auto + decltype (и опциональный declval), через operator,
      • Фиктивный шаблонный параметр-тип и decltype
      • Тип фиктивного шаблонного параметра-значения (можно сделать указателем и взять nullptr как значение по умолчанию)
      • Вспомогательный void_t: в специализациях шаблонных классов (второй параметр должен быть void)
  39. SFINAE — хитрости
    • 28-200512
    • Удаление перегрузок в зависимости от булевского условия, enable_if
    • Удаление исходно нешаблонных методов шаблонного класса через фиктивный шаблонный параметр
    • Упрощённый member detection после C++11 при помощи declval, decltype и ellipsis для самой низкоприоритетной перегрузки
  40. Parameter pack — основы
    • 30-200526
    • Template parameter pack, variadic template (в том числе специализации — у них может быть несколько паков)
    • Pack expansion, в том числе параллельный
    • Function parameter pack, автовывод нескольких template parameter pack из аргументов
    • Perfect forwarding для множества параметров
    • Fold expression (бинарный и унарный), трюк с лямбда-функцией для эмуляции цикла по элементам пака
  41. Parameter pack — детали
    • 30-200526
    • Возврат parameter pack невозможен, что с этим делать
    • Pattern matching + специализации для обработки элементов пака у классов
    • Pattern matching + автовывод параметров + перегрузки для обработки элементов пака у функций
    • Реализация std::tuple, std::get, std::tuple_size, std::tuple_element, std::make_tuple
    • Трюки с pack expansion: инициализацию массива (в том числе фиктивного до fold expression C++17), operator,

Прочие мелочи, не в билетах:

  • If-with-init statement (C++17, 26-200421)
  • Тип строковых литералов (27-200428)
  • RTTI
    • 26-200421
    • Что такое "полиморфный класс"
    • typeid от типа и от объекта, отбрасывание ссылок и верхней константности
    • const std::type_info& и std::type_index
    • Mangling имён и type_info::name()

Примеры дополнительных вопросов

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

Цель дополнительных вопросов — проверить, что если вы увидели странный код или хотите написать странный код, то знаете, в какую сторону копать или гуглить.

Дополнительные вопросы отличают 4 от 5.

  • Как можно реализовать TEST_CASE и CHECK(...) из doctest, чтобы при неуспехе выводилось сообщение об ошибке с номером строки и именем теста, а в конце программа завершалась с ненулевым кодом возврата?
  • Как реализовать функцию timed(f, arg0, arg1, arg2), которая идеально вызовет функцию f(arg0, arg1, arg2) (для произвольного количества параметров), идеально вернёт значение или исключение, а ещё всегда выведет на экран время работы?
    • Здесь надо совместить parameter pack (много параметров), perfect forwarding (идеальная передача аргументов с сохранением категории значений), decltype(auto) для возвращаемого значения (для идеальной передачи возвращаемого значения), конструктор/деструктор у локальной переменной (чтобы засечь время и всегда вывести, даже если вылетело исключение). Если совсем нечего делать во время ответа — можно пойти писать детали в 29-200519/code/02-perfect/07-timed-retval.cpp с добавлением variadic.
  • Как реализовать в классе BigInteger приведение типа к произвольному целочисленному?
    • Надо взять explicit operator T и ограничить тип T при помощи SFINAE и is_integral
  • Отличия vector::push_back(T) и двух методов push(const T&); push(T&&) по эффективности копирований/перемещений/деструкторов

Явно исключено

Все темы ниже не будут спрашиваться даже в качестве дополнительных вопросов.

  • inline namespace, псевдоним пространства имён (namespace s = std)
  • Многопоточность, thread_local
  • std::chrono, std::filesystem, std::random
  • Вариативные функции из Си
  • Приоритеты при выборе конструкторов из разных видов инициализации
  • Member detection idiom до C++11, определение точной сигнатуры функции
  • Precompiled header
  • Pimpl
  • Работа с индексами в parameter pack (std::index_sequence и прочее)
  • Ниблоиды
  • Архитектура Model-View-Controller
  • Аллокаторы STL
  • Использование for (auto &&x : vec) в обобщённом коде для корректной работы с прокси-объектом x
  • constexpr-классы
  • Включение/выключение полей в классе в зависимости от условия
  • В каких случаях STL предоставляет строгую гарантию
  • CTAD deduction guides
  • Шаблонные друзья
  • Empty base optimization
  • Рекурсивный вызов лямбд без std::function
  • Приоритеты перегрузок шаблонных функций вместе с нешаблонными функциями
  • Что происходит, если (не) написать return std::move(.....) (copy elision, temporary materialization)