С++, 1 курс, 3 группа, 2 семестр, 2016/17
Преподаватель: Егор Суворов (egor_suvorov@mail.ru, vk.com/egor.suvorov)
Префикс в теме письма: [C++TA]
Вопросы можно писать либо в ВК, либо на почту. В ВК быстрее отвечаю. Если вопросов много или они требуют вдумчивого ответа - лучше на почту.
Есть чат в ВК, там публикуются ответы на часто задаваемые вопросы, комментарии по лаборатным/домашкам и прочее. Также могут появляться общие комментарии по программированию и плюсам в частности. Я их буду время от времени переносить в раздел ниже, если заметили, что чего-то не хватает - перенесите. Копировать мои сообщения самостоятельно не стоит.
Содержание
Общие знания
Примеры с занятий лежат на GitHub.
Deadline и сдача лабораторных
По поводу deadline и попыток сдачи лабораторных (для домашек будут особенности):
- Дедлайн железобетонный в 23:59, если иное не объявлено в чатике. Если проверяю до дедлайна - беру последнюю версию. После после - последнюю, которая закоммичена до 23:59. Проверяйте, что все файлы добавились в репозиторий.
- Проверяю по возможности, одна попытка есть всегда, если успеваете отреагировать на замечания до дедлайна - то получается две, три, и так далее.
- К сожалению, пока что проверяю только в воскресенье днём-вечером, так что скорее попытка одна. Возможно, в будущем это изменится.
- Жёстких ограничений на количество попыток сдачи нет, но спамить не стоит. Процесс сдачи итеративный, но не интерактивный.
- Вы можете задавать вопросы в течение недели по любой теме: теория, "как правильно", "можно ли сделать так", "почему вот такой вот код на таком тесте выдаёт X, а не Y" (обязательно наличие кода и каких-то подробностей вроде "вот отчёт Valgrind и тест из одной строчки, с int работает, с Product - нет" - как на StackOverflow), "есть ли бросающиеся в глаза стилистические замечания?"
- Про проверку стиля в течение недели: не обещаю, что буду проверять так же внимательно, как и на "реальной" попытке сдачи. Можно присылать и куски кода, и общие вопросы ("куда класть тесты для вектора"), и весь проект целиком. Чем меньше кусок кода - тем быстрее и качественнее получите ответ.
- Для второй попытки сдачи требуется переоткрыть карточку в Trac: состояние reopened, "ожидает проверки", версия - 2.0 или 3.0.
- Можно использовать фишки, которые мы ещё не проходили, в том числе из C++11. Однако корректность их использования тоже будет проверяться. Умеете использовать (или хотите научиться) - вперёд.
- "Задача сдана" и "задача не сдана" - это условные состояния в Trac, которые я ставлю субъективно (например, прошло ли все автоматические тесты то, что должно было пройти). Они не влияют ни на баллы, ни на отчётность.
- Ставится максимальный балл за все попытки. Баллы за попытку считаются независимо. Например, если в одной вы получили 5 баллов за корректность и 0 за стиль, а в другой - 2 за корректность и 2 за стиль, то вы получите максимум из 5+0 и 2+2, т.е. 5.
- Если ваше решение не прошло тесты, то на код я по умолчанию не смотрю, за стиль ставятся условные 0 баллов. Это сделано для того, чтобы сэкономить моё время: наверняка код будет сильно изменяться в процессе исправления багов. Если вы всё-таки хотите, чтобы я прочитал код в попытке, которая не проходит тесты, вам нужно об этом явно попросить (переоткрыв тикет и написав комментарий вроде "проверьте, пожалуйста, стиль в попытках таких-то"). Несколько примеров:
- Вы прислали код, он не прошёл тесты, вы попытались исправить и у вас не получилось до дедлайна. Тогда в любой момент до 12:00 понедельника вы можете меня попросить прочитать код и выставить баллы за стиль.
- Вы прислали код, он не прошёл тесты, вы сделали ещё одну попытку, но тесты всё ещё не пройдены. Тогда вы можете попросить меня прочитать код любой из попыток (или даже обеих).
- Вы прислали код, он не прошёл тесты, вы сделали ещё одну попытку, она прошла все тесты. Тогда я буду проверять стиль кода именно в ней. Впрочем, вы всё ещё можете попросить меня проверить стиль кода в предыдущей посылке, но вряд ли это осмысленно - в ней было меньше баллов за корректность и вряд ли будет больше баллов за стиль (хотя кто знает).
- Тесты могут изменяться и добавляться по ходу проверки (если они всё ещё соответствуют заданию) по мере обнаружения всё более и более интересных багов. Уже выставленные баллы при этом не уменьшаются, если только они не были выставлены с пометкой "предварительно".
Полезные правила
- Правило трёх/пяти. На
&&
пока забиваем - это move-семантика, появилась в C++11, будет в конце семестра, там весело (теоретически похоже на ад, если стандарт читать, на практике применять просто). Пока что просто игнорируйте соответствующий конструктор и оператор. -
delete
иdelete[]
*корректно* разбирают случай "аргумент -NULL
", просто ничего не делает. Дополнительные проверки не нужны. - Если уж и копипастите - учитывайте эффект последней строки.
- Не используйте
#define
для объявления констант и функций:- Сколько-то причин перечислено тут
-
#define
работает на уровне препроцессора, до компилятора. Он довольно глупый: берёт и заменяет все вхождения одного слова на другое. Например, если вы используете его для объявления функций или констант, то это имя вы потом вообще нигде использовать не сможете: - Если вы используете
#define
для объявления функций, то из предыдущего пункта автоматически следует невозможность перегрузок функций. - В
#define
очень легко забыть поставить скобки вокруг аргументов или результата: http://ideone.com/AXjnVN -
#define
объявляется в одном месте, а подставляется в другом. Никак не проверяется, что мы не опечатались внутри#define
- может повезти: http://ideone.com/H8K2pg - Аналогично, даже если мы не опечатались, то всё равно может произойти что-то неожиданное: http://ideone.com/XZdj3f
-
#define
плевать хотел на все фигурные скобки и пространства имён. Объявили в одном месте - а он действует до конца файла. Нельзя завести "локальный"#define
(кроме как руками прекращать его действие при помощи#undef
). - Из предыдущего пункта следует, что при наличии
#define
в заголовочном файле все эти проблемы огребает не только ваш заголовочный файл, но и основной `.cpp` файл, а также все заголовочные файлы, включённые после вашего: http://ideone.com/q9CKRA
Полезные утилиты
- Для автоматического форматирования программ на C++ можно пользоваться либо какой-нибудь IDE (я верю, что Visual Studio, Eclipse, NetBeans, CodeBlocks и CLion все умеют форматировать; если не так - поправьте), либо консольными утилитами вроде clang-format или astyle. В качестве референсного можете использовать Google Code Style.
- gcov может показывать покрытие строчек кода тестами. Документация тут, читать пример со слов "Running the program will cause profile output to be generated.". Будьте осторожны с оптимизациями - если функция заинлайнена, то она в покрытии не показывается.
Примерные правила оценки лабораторных
Это больше руководство для меня и контрольные точки, чем чёткие правила; баллы могут сниматься и по другим причинам. Апелляции подавать можно и нужно - я мог что-то не заметить (например, что вы что-то на самом деле сделали, или что это ещё не проходили, или что в заданее не требуется), мог сделать слишком жёсткую систему оценки (тогда мы обсудим это с коллегами). Если что-то непонятно - задавайте вопросы.
Лабораторная 13 (массив со специализацией)
Правила описаны в задании.
Лабораторная 12 (вектора)
10 баллов распределяются так:
- За прохождение тестов и Valgrind (от 0 до 3 баллов):
- 0 баллов, если программа не компилируется или падает.
- 1 балл, если падает при запуске ваших тестов с каким-нибудь типом, кроме
int
иProduct
(удовлетворяющим, тем не менее, всем разумным требованиям). - 2 балла, если ваша реализация
my_vector
не прошла наши тесты. - 3 балла, если все тесты пройдены.
- -1 балл, если есть утечки памяти, но нет более страшных проблем.
- -2 балла, если есть undefined behavior вроде чтения из неинициализированной памяти (тогда -1 балл за утечки памяти не ставится).
- За тесты:
- 2 балл, если покрыты все строчки.
- 1 балл, если покрыты все методы.
- 0 баллов иначе.
- За качество и корректность интерфейсов классов (включая поля) и функций:
- 2 балла, если претензий нет.
- 1 балл, если в целом идея верная, но сделали что-то не слишкои опасное (открыты лишние методы которые не могут нарушить инвариант, просто есть лишние методы), или что-что, что обнаружится на этапе компиляции (забыли const qualifier).
- 0 баллов, если интерфейс опасен (забыли закрыть/реализовать оператор присваивания/конструктор копирования, открыт метод, который может нарушить инвариант, пространство имён после включения заголовка меняется слишком неожиданно).
- За качество и корректность реализации ставится от 0 до 3 баллов (субъективно). Снимаются за, например:
- -1 балл, если есть обширное дублирование кода, от которого можно избавиться (например, функцией).
- -1 балл за серьёзное несоответствие "традициям" языка C++ или за неожиданную логику программы.
- -1 балл за сильную (не)асимптотическую неэффективность (например, лишние вызовы конструкторов и выделения памяти).
28.02.2017 было произведено перемасштабирование: если баллы за пункты равнялись , , , , и - флаг "верно ли, что " (0 или 1; т.е. покрыты ли все методы), а - флаг "верно ли, что " (0 или 1; т.е. покрыты ли все строчки), то новый балл равен . Суммарный балл округляется до ближайшего целого, 0.5 округляется вверх.
Лабораторная 11 (I/O и полиморфизм)
Итак, 10 баллов распределяются (до 27.02.2017) примерно следующим образом:
- За прохождение тестов:
- 3 балла, если прошло всё и сразу.
- 2 балла, если потребовалось косметически поменять формат вывода текста (вроде `SalaryManager` и `Salary Manager`).
- 1 балл, если работает только текст (возможно, после косметических исправлений) или программа исходно не компилировалась.
- 0 баллов, если не удалось простыми изменениями заставить заработать.
- За Valgrind:
- 2 балла, если претензий нет.
- 1 балл, если есть только утечки памяти.
- 0 баллов, если есть undefined behavior вроде чтения из неинициализированной памяти.
- За качество и корректность интерфейсов классов (включая поля) и функций:
- 2 балла, если претензий нет.
- 1 балл, если в целом идея верная, но сделали что-то не слишкои опасное (открыты лишние методы), или что-что, что обнаружится на этапе компиляции (забыли const qualifier).
- 0 баллов, если интерфейс опасен (невиртуальный деструктор, забыли закрыть оператор присваивания/конструктор копирования).
- За качество и корректность реализации ставится от 0 до 3 баллов и снимаются за:
- -1 балл, если есть обширное дублирование кода, от которого можно избавиться (например, вынести в предка).
- -1 балл за скрытые ограничения (вроде фиксированной максимальной длины строки).
- -1 балл за серьёзное несоответствие "традициям" языка C++ или за неожиданную логику программы (нумерация массивов с единицы, реализация больших нешаблонных методов в header'ах, лишний код).
28.02.2017 было произведено перемасштабирование: если баллы за пункты равнялись , , , , то новый балл равен . Суммарный балл округляется до ближайшего целого, 0.5 округляется вверх.