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

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

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

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

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

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

Комментарии (48)


  1. Akuma
    12.08.2022 14:05
    +8

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

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

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


  1. Kelbon
    12.08.2022 14:18
    -1

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


  1. kuzhukin
    12.08.2022 14:29
    +19

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


    1. MarkWatney
      12.08.2022 14:39
      -3

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


    1. screwer
      12.08.2022 16:06
      +3

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


    1. a-tk
      12.08.2022 16:18
      +13

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


    1. anton19286
      14.08.2022 06:17

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


  1. amphasis
    12.08.2022 14:31
    +1

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


    1. fshp
      14.08.2022 22:21
      +1

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

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


  1. egor_nullptr
    12.08.2022 14:36

    Уважаемая редакция, указанная на скриншоте ссылка ведёт на страницу с ошибкой 404


    1. RobertLis
      12.08.2022 14:47

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


  1. crackedmind
    12.08.2022 14:39
    +7

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


    1. PyLounge
      12.08.2022 14:53
      +3

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


      1. Kelbon
        12.08.2022 21:11
        -1

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


    1. n0r3p1y
      12.08.2022 18:42
      +2

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

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


  1. Alex_Crack
    12.08.2022 14:47

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


  1. Lazerate
    12.08.2022 14:47
    +1

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


    1. crackedmind
      12.08.2022 16:12
      +2

      По поводу 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.

       


      1. Lazerate
        12.08.2022 20:48
        +2

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

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


      1. Kelbon
        12.08.2022 21:13

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


  1. Apoheliy
    12.08.2022 15:21
    +4

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

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


    1. kozlyuk
      12.08.2022 17:22
      +1

      Плюс там не сказано, что наследование не виртуальное и наследник прямой, а то и 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


  1. eisaev
    12.08.2022 16:05
    +1

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


  1. screwer
    12.08.2022 16:08
    +1

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


  1. ReadOnlySadUser
    12.08.2022 16:11
    +2

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

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


  1. Mingun
    12.08.2022 16:59
    +5

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


    1. da-nie
      13.08.2022 09:39
      +2

      Возможно, найти тест — первый вопрос теста. :)
      Я тоже нифига не понимаю, где сам тест. :) Так что, тест я не прошёл. :)


  1. Tujh
    12.08.2022 18:16
    +7

    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. ReadOnlySadUser
      12.08.2022 18:56
      -1

      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


      1. Lazerate
        12.08.2022 21:00
        +3

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

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


        1. ReadOnlySadUser
          12.08.2022 21:12
          -1

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


          1. Lazerate
            12.08.2022 21:19

            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


          1. Kelbon
            12.08.2022 21:23
            -1

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


            1. ReadOnlySadUser
              12.08.2022 21:47

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


      1. 0xd34df00d
        12.08.2022 21:13
        +3

        У меня есть некоторое впечатление, что компилятор, компилирующий


        volatile int n = ...
        int nn = n;
        if (nn != 1)
        {
          *static_cast<int*>(nullptr) = 42;
        }
        int m = nn;

        в код, эквивалентный


        int m = 1;

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


        Олсо, сам тест я тоже не нашёл. Видимо, не прошёл.


        1. ReadOnlySadUser
          12.08.2022 21:20

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


          1. 0xd34df00d
            12.08.2022 21:23
            +1

            Обратите внимание, что я специально один раз читаю из n в nn, и потом результат чтения из nn присваиваю в m.


            1. ReadOnlySadUser
              12.08.2022 21:46

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


              1. 0xd34df00d
                12.08.2022 22:58
                +2

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

                Это значит, что в nn будет единица. Там не может не быть единицы, потому что иначе в программе было бы UB, а его не бывает.


    1. 5oclock
      13.08.2022 00:03

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


    1. mastan
      13.08.2022 15:23

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

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


  1. GeorgeIV
    12.08.2022 18:48
    +2

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


  1. MUTbKA98
    12.08.2022 20:48
    +1

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


  1. RedWolf
    13.08.2022 17:41

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


    1. da-nie
      13.08.2022 19:59
      +1

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


  1. VedyNN
    13.08.2022 20:55
    +1

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

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


  1. da-nie
    15.08.2022 05:29
    +1

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

    Ссылки на тест тут просто нет.


  1. ryo_oh_ki
    15.08.2022 06:47
    +1

    5/8

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

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