?

Log in

No account? Create an account

Previous Entry | Next Entry

Немножко садизма


В одной книге по подготовке к программистским интервью попался следующий вопрос.





Дана программа:
#include <iostream>
class A {
    int n1;
    int n2;
public:
    A() : n2(0), n1(n2 + 2) {}
    void print() {
        std::cout << n1 << ", " << n2;
    }
};
int main() {
    A a;
    a.print();
    return 0;
}
Что будет распечатано?


Как братья и сестры программисты считают, это кошерный вопрос, или за такие вопросы надо сразу бить с ноги в щи?

Comments

( 26 comments — Leave a comment )
fizzik
Aug. 17th, 2015 02:12 am (UTC)
Надо бить. Ибо даже если в каких-то там стандартах что-нибудь сказано о порядке инициализации полей класса (в чем я сомневаюсь), то нормальный программист обязан забыть эту инфу немедлено по прочтении. А уж если он, не дай б-г, не только помнит это, но еще и использует, то его следует немедленно уволить.
solomon2
Aug. 17th, 2015 02:17 am (UTC)
С языка сняли :)
spamsink
Aug. 17th, 2015 05:06 am (UTC)
В стандартах это, естественно, сказано, поскольку деструктор должен вызывать деструкторы полей в определенном порядке, обратном порядку конструкции. Отсюда следует, что порядок вызова конструкторов полей определяется порядком объявления полей (если поле базового типа, то читать "инициализации" вместо "вызова конструкторов"). Нормальный компилятор на нарушение порядка записи инициализаторов по сравнению порядком объявлений жутко ругается. Я не удивлюсь, если в последних GCC и clang это по умолчанию просто ошибка.
solomon2
Aug. 17th, 2015 05:41 am (UTC)
Да, в стандарте это сказано, но писать такой код глупо и опасно. Во-первых, сегодня сказано, а завтра не сказано. Во-вторых, можно изменить порядок полей в определении класса при рефакторинге - и привет. В-третьих, тот, кто будет поддерживать такой код, будет гадать что происходит и выражаться нехорошими словами.

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

Автор книги завалил человека на интервью на этом вопросе и гордится этим.
spamsink
Aug. 17th, 2015 05:54 am (UTC)
писать такой код глупо и опасно.

Именно поэтому компилятор и ругается. Если не ругается, то начнет, если изменить порядок. Если по умолчанию это не ошибка, то -Werror is your friend.

сегодня сказано, а завтра не сказано

Не бывает.

Автор книги завалил человека на интервью на этом вопросе и гордится этим.

Логичен вопрос: должен ли человек при сдаче на водительские права мочь продемонстрировать базовое понимание механизма работы рулевого управления и пределов его возможностей?


solomon2
Aug. 17th, 2015 05:59 am (UTC)
Стандарты эволюционируют, а негодный код превращается в окаменелость :)

Признаюсь в страшном, я не очень хорошо представляю себе механизм рулевого управления и пределы его возможностей. Это не мешает мне десятки лет водить машину без единой аварии. У меня надо отобрать права? ;)
spamsink
Aug. 17th, 2015 06:03 am (UTC)
Что руль как ни крути, машина боком не поедет, ведь представляете себе? И как нужно крутить рулем, чтобы параллельно припарковаться? Просить продемонстрировать при сдаче на права умение параллельно парковаться достаточно оправдано, даже если человек заявляет, что он будет ездить из дома с гаражом на работу с паркингом и обратно, и поэтому ему совершенно не нужно уметь парковаться параллельно.

Также поверхностное знание языка программирования можно уподобить поверхностному знанию родного языка, когда человек может дожить до седых волос и так и не уметь правильно склонять числительные, например.
solomon2
Aug. 17th, 2015 06:10 am (UTC)
Если начать резко крутить руль при гололеде, то может и боком поехать. Вообще, вопрос о пределе возможностей руля решается экспериментально, но мне как-то не приходило в голову поэкспериментировать.

Язык для человека, а не человек для языка. Правильный годный код должен быть простым и поверхностным (= использовать необходимый минимум языковых средств).

Edited at 2015-08-17 06:12 am (UTC)
spamsink
Aug. 17th, 2015 06:58 am (UTC)
Правильный годный код и есть простой и поверхностный: пиши как хочешь, а поля инициализируются в порядке объявления. Если ошибся, компилятор тебя поправит. С тем, что вопрос довольно глуповат, я не спорю: он по стилю похож на вопрос, где нужно найти ошибку, например, разглядев разницу между 0l и 01.
Но сложным или недопустимым он от этого не становится.
fizzik
Aug. 17th, 2015 03:33 pm (UTC)
Не согласен считать "нормальным" компилятор, требующий инциализировать поля строго в том порядке, в котором они объявлены.

Такой компилятор не даст написать хорошо читаемый код. Поскольку в объявлении класса поля, как правило, должны быть сгрупированы по смыслу, а в конструкторе, если поля инциализируются его параметрами, наиболее понятно пишется и читается такой код, в котором инициализаторы следуют в том порядке, в котором соответствующие параметры встречаются в вызове конструктора. Порядок инициализации полей при этом следует считать неопределенным - так точно никакой ошибки не случится. Если неопределенность порядка вызова конструкторов полей вызывает какие-то сложности, значит сам класс криво спроектирован.
spamsink
Aug. 17th, 2015 04:48 pm (UTC)
Компилятор ничего не "требует", он просто согласно стандарту всегда инициализирует поля в том порядке, в котором они объявлены, потому что ему нужно заранее знать, в каком порядке их следует разрушать в единственном возможном у класса деструкторе, т.к. этот порядок должен быть противоположен порядку создания. Компилятор делает программисту одолжение, выдавая предупреждение, если глупый программист, не читавший стандарт, почему-то вдруг думает, что поля будут инициализированы в том порядке, в каком они написаны в конструкторе.

Если неопределенность порядка вызова конструкторов полей вызывает какие-то сложности, значит сам класс криво спроектирован.

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

fizzik
Aug. 17th, 2015 05:03 pm (UTC)
"Требует" - это я про Ваше предположение, что несоответствие порядка инициализатров полей порядку их объявления вызовет ошибку.
spamsink
Aug. 17th, 2015 05:14 pm (UTC)
Это не предположение, это утверждение, что оно вызовет предупреждение (оно таки вызывает), которое в целях дисциплины программирования полезно превратить в ошибку с помощью -Werror или аналогичной опции.
uccaxap
Aug. 17th, 2015 03:51 pm (UTC)

Для интервью - кошерный вопрос. На него меадринно отвечать двумя вариантами.
В работе - треф ллё сафек

solomon2
Aug. 17th, 2015 04:00 pm (UTC)
Экий вы талмудист :)
uccaxap
Aug. 17th, 2015 04:35 pm (UTC)
Даф йома - темплетыб операторы и динамо-кастинг средствами чистого С ( макро ле-тиферет)
ygam
Aug. 17th, 2015 03:14 am (UTC)
Бить по морде.
solomon2
Aug. 17th, 2015 03:24 am (UTC)
Я тоже так считаю, хоть это и опасно (автор вопроса - китаец, наверное кунфу знает :)
spamsink
Aug. 17th, 2015 05:07 am (UTC)
По-моему, совершенно честный простой вопрос.
ak_47
Aug. 17th, 2015 07:02 am (UTC)
Нет достаточно информации для ответа. Смотря как спрашивают. Если этот код даётся на интервью в качестве повода поговорить о инициализации, почему не надо так делать и пр - вот как вы это описали, то это хороший вопрос. Ваш ответ в комменте это именно то что я ожидал бы услышать от человека на интервью (или сам бы рассказал, буде спрошен).
solomon2
Aug. 17th, 2015 07:49 am (UTC)
Этот код давался для проверки, proficient ли кандидат в C++. О том, что это плохой код, речи не было. В книге приводится транскрипт заметок интервьюера, где он говорит, что он "very disappointed", что кандидат ошибся при ответе (предположил инициализацию в порядке аргументов). Лично я считаю, что человек proficient, если он может сам писать хороший код. Видеть сходу проблемы в заковыристом чужом коде - это канешно крута, но для этого есть дебаггер.
ak_47
Aug. 17th, 2015 11:10 am (UTC)
Инициализация мемберов и прочего вообще-то частый вопрос на интервью и входит в набор базовых знаний языка. Так что полностью отмести этот пример я не могу. То что в некоторых местах придают слишком большое значение буквоедству, это тоже не хорошо. Каждая контора в итоге для себя решает насколько им важны language lawyers или насколько виртуозно их программсты должны владеть языком.

При всём вышесказанном, некоторые конструкции должны вызывать у опытного программиста условный рефлекс как у собаки Павлова. Скажем, инициализация мемберов в конструкторе. Или там доступ к элементу в map через оператор [] должен зажигать лампочку в мозгу что если элемента в контейнере нет, то он будет добавлен. Вызов printf с неправильными параметрами. И т.д. и т.п.. Такие вопросы очень часто задают на интервью.

При этом, правильный ответ на эти вопросы ещё не означает что кандидат - хороший программист.
spamsink
Aug. 17th, 2015 04:50 pm (UTC)
Или там доступ к элементу в map через оператор [] должен зажигать лампочку в мозгу что если элемента в контейнере нет, то он будет добавлен.

Был в моем арсенале для интервью такой тест. :)
ak_47
Aug. 17th, 2015 11:49 pm (UTC)
Все мы вышли из страуструповской шинели. :)
eeik
Aug. 17th, 2015 11:48 am (UTC)
-Werror и ниче не напечатает. не скомпилируется.
solomon2
Aug. 17th, 2015 03:11 pm (UTC)
Не правда.
( 26 comments — Leave a comment )