Как стать автором
Обновить

Команда C++-программистов — @starik-2005, @PyLounge, @markwatney, @dmitrmax и @rssdev10 — собрала 8 экспертных вопросов по C++. Давайте посмотрим, что их вопросам сможет противопоставить команда хабрачитателей.

Осторожно, в комментариях будут спойлеры. Там от лица C++-команды выступят @rotor и @PyLounge: они объяснят, если в вопросах будет что-то непонятно.

P.S. Если хотите поучаствовать в создании будущих квизов, пишите редактору: тг, Хабр.

Дать каверзные ответы
Всего голосов 31: ↑23 и ↓8+15
Комментарии57

Комментарии 57

3/8 Вы неплохо справились, но...

Но вы не видели C++ уже 15 лет и то все ограничилось парой тестовых программ.

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

Был бы очень хороший тест если были бы хорошие вопросы и хорошие варианты ответов, а так не хорошее, хорошо?

Вопрос про интерфейсы странный. Да, в языке нет ключевых слов для определения интерфейса и для его реализации. Но язык позволяет определять интерфейсы в виде абстрактных классов и реализовывать их в дочерних в любом количестве.

Только в деталях это работает немного по-разному

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

Три слона ООП в С++: инкостыляция, поликостылизм, наследование костылей...

классика. Ж есть, а слова нет

Единственное, что поставило в тупик — вопрос с массивом char и cout... Но, я никогда не писал на C++ ¯\_(ツ)_/¯

К тому же там "верный" ответ неверный без деталей.

Если бы оператор был бы не определен для char без каких-либо ньюансов, то код просто не скомпилировался бы. Но из-за неявного приведения к int все работает. А этот ответ считается неверным.

Спасибо, починили.

В 7 вопросе для С++17 будет другой ответ.

Да, в 17 стандарте Order of evaluation всё же устаканили. Спасибо за замечание)

а ещё вы не указали функция это или конструктор и ответ вообще то различается. А ещё все остальные вопросы тоже херня

ну, вообще нет. ответ на этот вопрос всё тот же. в С++17 по большей части коснулись побочных эффектов при вызове функции, но сами же вычисления параметров до сих пор остаются indeterminately-sequenced.

https://en.cppreference.com/w/cpp/language/eval_order

Не очень-то и каверзные вопросы.
Пишу на С++ без малого всего год, а получилось ответить верно на 7 из 8.
А вообще из-за того, что в стандарте не прописано строго, как должны быть реализованы некоторые вещи, то и возникают потом "каверзные" ситуации.

А вы уверены, что составители теста знали С++? Или они застряли где-то в прошлых стандартах, и то не до конца изучив их? Например вопрос про порядок вызова функций имел бы другой ответ в С++17. Последний вопрос бредовый, ибо ладно, допустим, что не запрещено действительно Может быть уб... Но и разрешено тоже, в общем-то, т.к. уб ещё никто не запрещал – это просто поведение, на которое стандарт не налагает никаких требований. Что значит запрещено вообще, ill-formed? С volatile бред, конечно. Нет, абсолютно, совершенно нет, значение слова volatile не отключение компиляторных оптимизаций. Потрудитесь перед составлением теста убедиться в собственной экспертизе.

По поводу volatile давайте заглянем в стандарт https://eel.is/c++draft/dcl.type.cv#6

[Note 5

volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation.

 

Furthermore, for some implementations, volatile might indicate that special hardware instructions are required to access the object.

 

Спасибо за подтверждение моего тезиса. Наверно, теперь всем очевидно, что да, volatile указывает компилятору на то, что следует избежать оптимизаций, но это не предназначение, а _потому что_ "because the value of the object might be changed by means undetectable by an implementation". Как можно заметить, выключение ряда оптимизаций является следствием. Т.е. волатайл обозначает переменную, которая может быть изменена извне. Он не выключает абсолютно все оптимизации, это и не является целью. Если бы компиляторщики нашли способ агрессивно оптимизировать даже в случае изменений извне, они бы это сделали. В тесте же единственное предназначение волатайла для отключения оптимизаций. Смешно.

Не учитывая того факта, что это ненормативная часть стандарта, Note. Что-то вроде разъяснений, которые не дают никаких гарантий.

И тут написано что это Note, по стандарту volatile значит, что для переменной отсутствует гарантия. А эффекты с оптимизациями это следствие отсутствия гарантии. Стандарт ничего про оптимизацию не знает и не должен знать(за исключением гарантированных EBO/ NRVO/RVO)

Вопрос про static_cast / dinamic_cast лучше как нибудь уточнить. При таком задании (не сказано про отсутствие любых virtual-ов) может быть и так и так. Иногда рекомендуют в общем случае использовать dynamic типа оверхед небольшой, но явно надёжнее.

Вопрос про интерфейсы тоже лучше переформулировать. ключевого слова нет, но концептуально это всё делается штатными средствами.

Плюс там не сказано, что наследование не виртуальное и наследник прямой, а то и static_cast может быть запрещен:


If B is a virtual base class of D or a base class of a virtual base class of D, or if no valid standard conversion from “pointer to D” to “pointer to B” exists ([conv.ptr]), the program is ill-formed.

https://eel.is/c++draft/expr.static.cast#2

"Завершить тесь"

В конце пишет "тесь" вместо "тест"

8/8, за исключением того, что я на последний вопрос намеренно ответил "запретим потом" шутки ради.

Правда вопросы не особо-то сложные.

А сам тест-то где?

Возможно, найти тест — первый вопрос теста. :)
Я тоже нифига не понимаю, где сам тест. :) Так что, тест я не прошёл. :)
  1. Ответ про volatile не корректен. Это ключевое слово указывает компилятору, что данную переменную следует читать непосредственно из источника (появилось для непосредственного чтения данных из портов ввода-вывода в чистом Си).

    a volatile object is one whose value might change spontaneously. That is, when you declare an object to be volatile, you're telling the compiler that the object might change state even though no statements in the program appear to change it

    Как следствие этого требования компилятор отключает кеширование значения в регистрах и кешах процессора, которые действительно являются оптимизацией, поэтому отключение оптимизации для volatile переменных - это побочный эффект, а не основное предназначение, тем более в те времена, когда вводилось это слово оптимизирующих компиляторов не сушествовало, равно как и языка С++, между прочим, это легаси из чистого Си.

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

1.

Открываем стандарт

volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation. Furthermore, for some implementations, volatile might indicate that special hardware instructions are required to access the object

Т.е. вот прям в стандарте написано, что для начала volatile - это подсказка компилятору, что вот тут оптимизировать никак нельзя, а уже потом, возможно, для каких-то архитектур, это будет означать специальные инструкции для чтения/записи, учитывающие кэш-процессора и пр.

2.

Можно и отрывать, конечно, но не так уж много выбора при компиляции с -fno-rtti

Просто чтобы вы понимали, то, что написано в Note, не значит, что стандарт говорит, что компилятор обязан не оптимизировать. Note – это разъясняющая, ненормативная часть стандарта, которая не даёт никаких гарантий. Их, конечно, пишут, чтобы дать дополнительное объяснение и обычно они соответствуют реальности... Хотя, например, есть ноуты, в которых написано, что разыменование nullptr это UB, хотя сам стандарт этого не доказывает.

В любом случае вы выделяете почему-то совершенно неверные части разъяснения. Вы должны были выделить "because the value of the object might be changed by means undetectable by an implementation". Это причина. Это то, что обозначает волатайл. То, что компилятор не оптимизирует агрессивно, хотя _всё равно_ оптимизирует, лишь следствие, т.к. если бы он слишком агрессивно оптимизировал, наблюдаемое поведение программы могло бы отличаться от написанного, что запрещено. Я надеюсь вы умеете отличать причину от следствия?

Так вопрос и не задаётся в стиле "в чем причина") Вопрос "что даёт использование volatile". И в стандарте чётко расписано к чему приведет использование volatile

Note – не является нормативной частью стандарта. Это не является гарантией, note не обязывает компилятор это выполнять. Правильным ответом было бы "указывает компилятору, что значение данной переменной может неожиданно измениться извне..." К этому можно было бы добавить "... вследствие чего агрессивные оптимизации обычно отключены для переменных с этим квалификатором".

По сути всё, что говорит стандарт на тему волатайла, это именно эта часть: https://eel.is/c++draft/dcl.type.cv#5

Note ниже просто дополнительное объяснение, помощь в трактовании. Но никак не точное значение, гарантия или обязательство для имплементации.

Если интересует где можно понять, почему Note не даёт никаких гарантий, то рекомендую посмотреть вот этот документ, часть 8.2: https://www.google.com/url?sa=t&source=web&rct=j&url=https://ec.europa.eu/eurostat/cros/system/files/ISO%2520reference%2520definitions%2520-%2520%2520guide%25202%2520-%25202004%2520-%2520rev.doc&ved=2ahUKEwjc2rHU9MH5AhVUCBAIHdL5CNkQFnoECCUQAQ&usg=AOvVaw2nLbbk204oJGuKGPgGyuGR

а в соседнем вопросе ФОРМАЛЬНО ИНТЕРФЕЙСОВ НЕТ В С++ считается верным ответом, очень последовательно и логично(НЕТ)

Но формально в C++ и правда нет интерфейсов)

НЛО прилетело и опубликовало эту надпись здесь

Я не согласен. Даже с учётом UB под условием, компилятор сгенерировать код по чтению из n хотя бы в m

НЛО прилетело и опубликовало эту надпись здесь

Да, и я о том же. В if-ветке к нас UB, так что компилятор может её выкинуть полностью, но это вообще не значит, что чтение из n вернёт единицу. Это разные события в мире С++. Компилятор обязан сгенерировать код чтения из volatile, но не обязан генерировать UB ветку кода.

НЛО прилетело и опубликовало эту надпись здесь

А кэширование в кэше можно как-то включать и отключать?

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

А как же CRTP? Его статический полиморфизм держится как раз на static_cast к наследнику.

Можно и на чистом Си писать в ООП стиле, заполняя аналог VTBL вручную (очень частая практика во встроенных системах), вот только я бы не назвал это хорошим стилем программирования, отладка подобного превращается в кошмар очень быстро.

getinfo() и getInfo(), C++ регистро-зависиммый

ПривЕдение, все ж.

Нужно обладать богатой фантазией, чтобы назвать эти вопросы каверзными. Половина из них вообще на общее развитие, независимо от языка. Я вот на с++ 20 лет не писал, но на 6 из 8 ответил

Да где вы этот тест все берёте-то? :O Я не вижу ссылки. И я в этом не одинок (см. выше вопрос).

Касательно интерфейсов все скользко так как само слово часто фигурирует в том же стандарте при описание работы пространства имен и доступа к методам внутри структур, там не стесняются писать слово интерфейс ))

Вопросы интересные, но на вкус "блюстителей стандартов", слабовато будет.
Есть куча запарных тем на подумать, те же лямбды, и куча мест с неопределенным поведением (неожидаемым) в новых стандартах.

Так. И всё-таки, я бы хотел увидеть, где тут этот тест.
Вот что показывает последний FireFox.

Ссылки на тест тут просто нет.
У меня аналогичная ситуация, но в Vivaldi. А вот Firefox ESR и Konqueror нормально отобразили тест.
Было бы интересно узнать, как оно так получилось.

5/8

Может ли класс в С++ реализовывать сразу несколько интерфейсов?

Составитель вопросов не знает, что интерфейсом в С++ называют чистый абстрактный класс. Отдельного ключевого слова не требуется. Мало класса? Есть шаблоны.

как то просто и без фантазии.

В чем отличие "void foo();" в C++ и в C?

НЛО прилетело и опубликовало эту надпись здесь

Только вопрос с cout запорол, но это не мудрено, этой дичью языка ни когда не пользовался. Принтфы на порядок удобнее и понятнее как по мне, а с приходом формата и переучиваться не надо и стало всё ещё проще и надёжнее.

6/8 и я не прочитал ни одной книги по C++ программированию. Самоучка :)

Вопросы про касты и интерфейс не корректны. С++ представляет интерфейсы в виде абстрактных классов, поэтому говорить, что их нет, потому что нет ключевого слова interface - это от незнания языка.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий