Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Задача 1.
- CE возникает из-за того, что выражение (x > 0 ? ++x : x++) является rvalue, а ему нельзя присваивать.
- Даже если изначально проинициализировать x=1, CE не исчезнет. Хоть ++x сам по себе является lvalue, компилятор обязан принять решение относительно всего выражения (x > 0 ? ++x : x++), чем оно является. Поскольку одна из частей является rvalue, то и все выражение целиком является rvalue, значение x роли не играет.
- Задача 2.
- Возможны 6 вариантов: цифры 123 могут образовывать любую перестановку, на конце обязательно будет 7.
- Хоть приоритет оператора * и выше, чем +, нет гарантий относительно того, в каком порядке будут вычисляться значения самих аргументов. У каждого из операторов может сначала вычислиться левый операнд, потом правый, а может наоборот. Отсюда unspecified behaviour.
- NB: за ответ “возможны всего 4 варианта” баллы не снижаем. Это детали стандарта, в которые мы не лезем. Главное - наличие пояснения, что порядок 123 не определен, но 7 обязательно будет в конце.
- Задача 3.
- Выведется 2323. Функции inc_value и assign_value_from_ref никак не меняют переданные параметры, так что можно считать, что этих функций нет.
- inc_ref(a) увеличивает а (то есть х) на 1.
- inc_ref(b) увеличивает b (то есть y) на 1.
- assign_ref_from_value(b, y) ничего не меняет, поскольку b и так равно y.
- В итоге получаем вывод 23, после чего еще раз то же самое 23.
- Задача 4.
- Тут проблема в том, что поле int& y ничем не проинициализировано перед входом в конструктор. Надо написать список инициализации вместо присваивания полей: A(int xx, int yy): x(xx), y(yy) {}. Конструктор копирования менять не нужно, он сам нормально сгенерится. Правда, теперь есть новая проблема - UB из-за того, что поле y будет висячей ссылкой, ну да вопрос уж не об этом.
- Задача 5
- Ну тут все очевидно, нужен нетривиальный копи-конструктор и оператор присваивания. Проверить, что правильно объяснили проблему и правильно их реализовали.
- Задача 6
- Тут надо написать перед мэйном класс-компаратор, определить в нем оператор () как надо, а в самом сете указать его шаблонным параметром.
- Задача 7
- Будет acbABCA.
- Сначала создается объект B. При этом сначала создается родитель (а), потом поле наследника (с), потом сам наследник (b).
- Потом происходит срезка и копируется родительская часть. Ничего при этом не выводится.
- Потом уничтожается объект А (который был копией исходного).
- Потом уничтожается исходный объект: сначала деструктор наследника (В), потом поля наследника (С) и в конце родитель (А).
- Задача 8.
- В строке 1 ошибки не будет: Mom может обратиться к полю своего непосредственного родителя, т.к. оно protected.
- В строке 2 тоже ошибки не будет. Son может обратиться к полю m своего непосредственного родителя, хоть оно и private, но там написано friend class Son. К полю g он может обратиться, поскольку хоть Granny и приватный родитель, но мама к ней пускает (сын - друг для мамы), а у бабушки поле уже protected, а не private.
- В строке 3 будет СЕ во всех трех случаях. s.s защищенное поле, s.m приватное поле, а s.g недоступно, потому что хоть у бабушки и написано friend int main, мама к ней не пускает (наследование приватное).
- Задача 9
- s.g вызывает неоднозначность из-за ромбовидного наследования (важный момент: приватность тут не играет роли, ошибка именно по причине неоднозначности, т.к. доступы проверяются после выбора версии).
- static_cast<Mom&> вызывает ошибку доступа, т.к. наследование приватное.
- static_cast<Dad&> ошибку не вызывает, но обращение к полям все равно вызывает CE, т.к. поля приватные.
- Если заменить на reinterpret, то пропадет ошибка из-за запрещенного каста. Однако обращение к полям все равно нигде работать не будет, т.к. они по-прежнему все приватные.
- Задача 10
- В первом случае выведется 21. 2 - очевидно, а 1 - потому что f в классе Derived реально не оверрайдит f из класса Base (сигнатура не совпадает). Поэтому выбирается версия для Base.
- Если раскомментить override, то будет CE - как раз потому, что f обещала оверрайдить, а на самом деле не оверрайдит.
- Задача 11
- Поскольку деструктор родителя вызывается после деструктора наследника, а деструктор родителя не определен, возникает ошибка линковщика. Надо дописать определение деструктора. Сделать это надо вне тела класса: Base::~Base() {}
- Если удалить виртуальный деструктор, то для переменной b не будет вызван деструктор Derived, а будет вызван лишь неявно сгенерированный пустой деструктор Base. Как следствие - delete dp не будет сделано, это потенциальная утечка памяти.
- Задача 12
- Компилятор сначала выбирает подходящую версию перегрузки, а затем выбирает подходящую специализацию этой версии, если таковая имеется. В первом случае f(T, T) выигрывает у f(T, U) и поэтому выбирается f(T, T), а специализаций у нее нет. Во втором случае f(int, int) становится специализацией f(T, T), а не f(T, U), поэтому выбирается эта специализация, а не оригинальная версия f(T, T).
- Задача 13
- Параметром шаблона не может быть неконстантная переменная, т.к. компилятор должен в момент компиляции во все шаблоны подставить фиксированные значения переменных, а он не может так поступить с неконстантной переменной. Все заработает, если просто объявить n как const size_t.
- Задача 14
- По стандарту компилятор парсит строку S<T>::x * a; как выражение, а не как объявление. Он не может парсить ее по-разному в зависимости от T, так как он должен еще до шаблонной подстановки уметь проверять корректность синтаксиса, в частности, отличать объявления от выражений. Поэтому возникает ошибка “а - необъявленная переменная”. Можно исправить ошибку двумя способами: 1) дописать typename перед этой строкой, и тогда он будет парсить это как объявление; 2) объявить переменную a где-то перед этой строкой, тогда он успешно распарсит это как выражение.
- Задача 15
- Например, так:
- template<typename T>
- struct remove_all_extents {
- using type = T;
- };
- template<typename T>
- struct remove_all_extents<T[]> {
- using type = remove_all_extents<T>;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement