company_banner

C++ в Практикуме. Как обучить студентов плюсам, не отпугивая

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

    Меня зовут Антон Полднев, я уже давно пишу в Яндексе на C++ и руковожу сервисом, написанным на этом языке. Параллельно я учу других людей навыкам разработки. С 2016 года я вёл курсы на Coursera, затем мы их прокачали и сделали на их основе курс для Практикума. В этом посте я расскажу, как мы учим людей C++, а также про основные особенности этого языка. 

    Языковые сложности. C++ VS Python   

    Да, плюсы́ — не такой популярный язык для студентов, как тот же питон, например. Если мы говорим о человеке, который решил впервые попробовать свои силы в программировании, то он с большей вероятностью пойдёт писать именно на Python, нежели на C++. Здесь дело и в пороге входа, который у плюсов ощутимо выше, и в том, что на Python куда проще получить в результате своих трудов полноценную работающую программу. Ведь там многое доступно сразу из коробки, нет лишних скобочек и связанных с ними сложностей. Работа с файлами там тоже заметно проще — в общем, просто берёшь и работаешь. 

    Сейчас даже в школах, где уделяют внимание программированию, учат способных учеников именно Python. Конечно, многие из нас с вами на уроках информатики начинали с Pascal или Visual Basic, в ряде школ наверняка они ещё остались. Но проблема Pascal в том, что обучиться-то ему можно, а вот найти применение в реальной жизни уже сложнее. А Python и простой, и дружелюбный, и проектов на нём много. 

    — Погоди, пост же про плюсы, — скажет внимательный читатель. Да, всё верно, вот и они. Штука в том, что с Python хорошо начинать. А вот дальше всё зависит от задач и желаний программиста. Если вам хочется (и интересно) писать куда более производительный код, над которым у вас будет полный контроль, то для этого понадобится что-то низкоуровневое. Например, Java, C++, C#, в какой-то степени Go. 

    И в этой низкоуровневости заключается двойственная природа плюсов. С одной стороны, язык изначально сам по себе низкоуровневый, и это круто. С другой стороны, его не очень удобно использовать. Если вы что-то сделаете не так, создавая программу на каком-то другом языке, она будет работать неэффективно или работать с ошибками. Плюсы же не прощают ошибок, и вместо неработающей программы вы вполне можете получить инферно, утягивающее в Страну Вечной Охоты всё, до чего дотянется. 

    Это так себе история, поэтому за плюсы активно взялись в начале XXI века и начали развивать язык. Как итог, сейчас на C++ не просто можно писать эффективный код. На C++ стало приятно писать эффективный и безопасный код. 

    Обузданная мощь

    В плюсах, как и в других компилируемых низкоуровневых языках, есть статическая типизация кода, которой нет в Python. Благодаря ей вы можете чётко и ясно объявить, что такой-то объект имеет вот такой тип данных, что вот эта штука — число. И всё, после этого оно не станет, скажем, строкой. И это даёт возможность компилятору генерировать более эффективный код. 

    Программы на C++ быстрее благодаря более чёткой типизации
    Программы на C++ быстрее благодаря более чёткой типизации

    Программируя на C++, вы на самом деле чувствуете мощь — у вас куча возможностей. Как говорили в таких случаях Питеру Паркеру: «С большой силой приходит большая ответственность», что, кстати, тоже является хорошим стимулом для обучения. 

    Если вам интересно создавать эффективный код и в процессе перелопачивать огромные объёмы данных, то дополнительным челленджем в C++ станет не просто написать быстрый код, но написать его так, чтобы он был понятен остальным. Люди же будут его использовать, поддерживать и масштабировать — это не вещь в себе, это инструмент. Хороший, работающий и ремонтопригодный. 

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

    К счастью, у C++ за всё время накопилось множество хороших практик того, как писать понятный и поддерживаемый код. И это тоже интересный момент в плане обучения: задача усложняется, потому что у вас в руках уже не просто язык посложнее, но при этом и огромный набор инструментов, чтобы на нём хорошо писать. Этому тоже важно учить.

    Как не надо учить людей C++

    Хотя я выше и писал, что частенько в плюсы приходят из Python в поисках силы и контроля, лично я знаю не так уж и мало людей, для которых C++ стал первым языком. 

    Идеальный путь мне видится примерно таким. 

    • В школе у вас было программирование, вас учили питону.

    • Затем вы аккуратно и постепенно переползли на плюсы.

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

    Это если сильно всё упрощать.  

    На самом деле для большинства ситуация выглядит примерно так.

    • В школе программируете на чём-то, что вроде бы и язык программирования, при этом совершенно бесполезный и в природе уже не встречается. Кроме учебников. Старых учебников. 

    • Затем поступили в университет, а там — сюрприз — внезапно плюсы. 

    Но и это еще не всё. Вдобавок можно попасть на максимально академический курс. Там вам расскажут, что лет двадцать назад вот эти бородатые мужики придумали С, а вот указатель на память, под которым что-то может быть, напишите 10 строк кода и узнаете, что именно. 

    В общем, про метапрограммирование вы на таком курсе услышите разве что от других студентов. И то не факт. 

    Так нельзя делать, и вот почему. Допустим, новичку рассказали про С, попросили сначала (на курсе по C++, да) попрограммировать именно на С. Если элемент страдания на курсе возведён в культ, то студенты будут программировать ещё и на ассемблере, просто для того, чтобы ощутить ту боль и метания, которые испытывали инженеры. 

    Да, будет что рассказать у костра на конкурсе страшных историй. Но такой подход почти неминуемо вызывает отторжение ко всему семейству языков. И прелесть плюсов до человека, напуганного С и ассемблером, вы просто не донесёте. Разве что его нервная система будет очень крепка. Но тут не Спарта же, мы людей учим. 

    Менее страшный академический подход будет заключаться в том, что после С вам всё же расскажут про плюсы: смотрите, вместо массива есть вектор, и у него динамически изменяется размер, и всё делается за вас. И вроде как студентам радостно должно быть: круто-то как, само всё работает. Но зачем же тогда студентов перед этим полтора семестра заставляли вот этими руками писать по 50 строк кода, когда такая круть существует?

    — А как надо?

    А надо просто рассказать людям, что программирование — это не страшно, что можно научиться писать полезные программы, небольшие, на 10–20 строк. Потом плавно переключиться на C++ и показывать, как там всё круто работает и какой хороший код получается. 

    Этот подход мы применяли на Курсере. Он же у нас и в Практикуме: покажем человеку, какой язык классный. Классный сегодня, без попыток углубиться в историю и рассказов о его предыдущих архивных версиях. Просто покажем, как создать массив чисел. Или массив котиков, например. 

    Например, вот так мы объясняем студентам цикл while через хождение к холодильнику
    Например, вот так мы объясняем студентам цикл while через хождение к холодильнику

    Мы сразу говорим студенту, что если хочется набор объектов — используй тип «вектор». Он сам себе выделит память, сколько ему там надо, всё будет ОК, вообще в этой ситуации не думай про управление памятью. Хочется сделать множество элементов, которое можно быстро добавлять и искать в нём — вот тебе контейнер, без проблем. 

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

    А получается, что классическое образование и академический подход в этом плане занимаются археологическими раскопками, причём снизу вверх — с первого уровня, потом просто по хронологии, наслаивая все вехи развития языка. Чтобы через семестр стало понятно, что почти всё из услышанного ранее просто когда-то использовалось, да, но конкретно вам уже не пригодится. И спасибо за внимание. 

    Мы учим студентов на курсе, начиная с верхнеуровневых вещей, и потом уже раскрываем всё это подробнее, углубляясь в каждую тему. Про устройство контейнеров можно рассказывать уже через пару месяцев обучения, это тоже помогает разработчику прокачиваться. Потому что в отличие от других языков все стандартные средства, например, контейнеры C++ тоже написаны на C++. И мы даём задачки вида «Вы узнали, как на самом деле работает управление памятью. Теперь напишите свой список или вектор». 

    Всё это мы даём примерно в конце первой половины обучения, чтобы понять, как всё работает изнутри. 

    Обучение углублённым темам

    В плюсах есть множество тем, в которых можно дополнительно попрактиковаться и расширить свои возможности. Например, динамический полиморфизм. Это когда мы пытаемся отчасти приблизиться к Python и заявить: этот объект имеет не совсем фиксированный тип и может быть то числом, то строкой. Но всё это происходит под вашим контролем! И потому всё ещё максимально эффективно для вашей задачи.

    С другой стороны, есть полиморфизм статический — механизм, благодаря которому можно писать универсальный код, работающий для разных типов данных. Он выполняется так же эффективно, как код, заточенный под конкретный тип, и всё ещё легко читается. В общем, если вы что-то слышали про метапрограммирование — это оно. А самое приятное, что язык развивается и всё больше упрощает подобные сложные задачи.

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

    C++ в Яндексе

    А теперь расскажу, как C++ пригождается нам внутри компании. На нём хорошо писать сервисы, которые критичны с точки зрения нагрузки и скорости ответа. Сейчас я руковожу отделом разработки баннерной системы. Это сервис, отдающий рекламу на конкретный запрос конкретному пользователю. Рекламу мы показываем и на поиске Яндекса, и на других сайтах — соответственно, трафика через нас проходит огромное количество. Бо́льшую часть прибыли Яндексу приносит именно реклама. Это важный сервис, и он написан на C++. 

    К рекламному движку, как мы его называем, предъявляются жёсткие требования по нагрузке: за секунду нужно обрабатывать сотни тысяч запросов, и делать это нужно за десятки–сотни миллисекунд. Спроектировать и поддерживать такой сервис довольно тяжело. И современный C++ нам в этом помогает.

    Известный всем поиск Яндекса сталкивается с похожими проблемами. Он тоже написан на плюсах, и наши команды активно обмениваются опытом разработки и проектирования высоконагруженных сервисов. Или взять, например, браузер: он должен быть эффективным и не замедлять систему пользователю, который установит его на свой компьютер и откроет пару сотен вкладок. Тоже C++, и тоже челленджи.

    Чеклист «Как надо»

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

    • Убедитесь, что вы начали рассказывать про язык, а не про историю развития этого языка. 

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

    • Вообще не страшно рассказать про вектор и при этом не рассказать про шаблоны классов. Детали реализации обсудить всегда успеете. 

    • А ещё не страшно рассказать про словарь и не рассказать, что такое бинарное дерево. 

    • Не усложняйте. Любая популярная идея в своём ядре понятна и проста. Если это не что-то хитрое типа метапрограммирования, то про это не надо рассказывать сложно. Пусть, например, вы рассказываете про активное использование ссылок. Ссылки в массе своей пришли на замену указателям. Поэтому расскажите про ссылки и не рассказывайте про указатели. До поры до времени.

    • Расскажите про важность алгоритмов, хотя бы базово. Потому что плюсы — про эффективность. Нужно уметь оценить, что алгоритм А работает за линейное время, а алгоритм Б — за квадратичное. Поэтому первый будет быстрее, ведь линейная сложность лучше квадратичной. Это полезная теория. 

    • Убедитесь, что студент понимает, зачем вы ему это рассказываете. Если вы решили рассказать про словарь просто потому, что словарь — это круто, студент может не понять. Покажите, зачем ему словарь. 

    • Рассказывайте про новое в языке. Быть современным важно. 

    • Не рассказывайте вообще всё. Это ловушка для преподавателя: когда вы давно в C++ и хорошо знаете язык, хочется рассказать про него всё. Рискуете перенасытить студентов и усложнить подачу. 

    А усложнять не надо. 

    Вот так мы и учим наших студентов. Если у вас есть вопросы, с радостью отвечу.  

    Яндекс.Практикум
    Помогаем людям расти

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

      0

      А есть ли смысл изучать сейчас плюсы, если есть Go? Действительно интересно.

        +14
        Вместо Go подставьте любой популярный не С/С++ язык, и задайте этот вопрос снова.
        Изучать стоит то, на чем собираешься работать.
        А знание основ С++ дает возможность более легкого вхождения в изучение другого ЯП.
          +13

          Знание основ хоть какого-нибудь ЯП даёт возможность более лёгкого вхождения в изучение другого ЯП.

            0

            В моем вопросе речь была совершенно про другое. Я не спрашивал про первый язык. Вопрос был именно про Go vs С++, в контексте того что у Go сообщество развивается стремительно, интересные запросы по работе. Так же не в одной статье видел про то что на данный момент лучше изучать Go чем С++. Поэтому и спросил у автора поста, учитывая его опыт.

              +2
              Для back-end'а — да, пожалуй Go больше распространен. Но если не ограничиваться вебом — на фоне плюсов Вы Go даже не заметите. А «интересно» — это субъективно, я вот вообще не понимаю, что в вебе может быть интересного.
          +3

          Во-первых, на C++ уже написано очень много кода — тот же Chromium. Или Кликхаус. Ну и разные сервисы в больших компаниях, в которые вам может захотеться поконтрибьютить изнутри. Сюда же можно отнести большое комьюитини и огромное количество библиотек под разные платформы.
          Во-вторых, Go стремится к низкому порогу входа, и из-за этого некоторые задачи на нём решаются более многословно. (Но местами Go, безусловно, компактнее.)


          Мне пока не кажется, что один язык полностью заменит другой. Скорее, будет как с Java или C#, и каждый займёт свою нишу.
          Поглядим лет через 50 :)

            +1

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

            +4

            s/Go/Rust

              +2

              А это спорный вопрос — есть ли Rust? Я активно с ним работал, он мне очень нравится, но с моей точки зрения его ещё нет. В стабильном Rust, например, нет способа определить оффсет поля не прибегая к тому, что является UB, хотя и работает на практике. И много чего ещё нет, много недоделанного. Везде строительные леса, подпорки и чего-то законченного в обозримом будущем (ближайшие несколько лет) не ожидается.

                –1
                Более того, его в обозримом будущем и не будет. Мозилла явно не в лучшей форме, чтобы его тянуть, а больше он особо никому и не нужен. Rust ждёт судьба языка D — по всем статьям лучше плюсов, но нет никого, кто бы его протянул в мир реального программирования.

                Небольшая надежда есть только на то, что где-нибудь в США кто-то топнет ногой и скажет «всё, блин, ПО для атомных станций и самолётов больше писать на сишке нельзя, только Rust или что-то с не меньшей степенью защиты». Вот тогда да, появятся и вакансии и проекты.
                  –1
                  Мозилла явно не в лучшей форме, чтобы его тянуть, а больше он особо никому и не нужен.

                  А вы можете так нагло не врать? Если уж на то пошло, Rust изначально был разработан Грейдоном Хоаром в качестве личного проекта, к спонсированию которого Mozilla подключилась значительно позднее. А помимо Mozilla, Rust используется в проде у Cloudflare, Amazon, Dropbox, NPM, 1Password и ещё дофига других компаний, так что нет, Rust в обозримом будущем с таким количеством заинтересованных в нём лиц никуда не денется.

                    0
                    Без сомнения. Для небольших критических модулей или новых проектов. И все, кто его попробовал, приходят к мнению, что переписывать ВЕСЬ код на С/С++ на расте тупо не выгодно. Затраты на мероприятие не окупятся потенциальной прибылью от меньшего количества багов.
                      +2

                      Гм. А в Firefox именно что заменяют код, написанный на C++

                        +1
                        При первых же финансовых проблемах Мозилла в первую очередь попёрла команду Servo и Rust-программеров. Как после этого можно серьёзно относится к их попыткам заменить код?
                          +4

                          Можно вспомнить годовую компенсацию Митчелл Бейкер и понять их приоритеты.

                    +1
                    Ходили слухи, что для спутников, электронного голосования и пр. код на Cobol, и никто ножкой не топнул. Не знаю, насколько правда, но если правда — то от С вообще никогда не избавятся…
                      +1
                      Дело может изменить какая-нибудь большая катастрофа.
                  +3

                  Вам придётся изучать и C и C++ хотя бы уже для того, чтобы писать рабочие и качественные обертки для интеропа раста с массой уже существующих библиотек на этих языках (если вы в бизнес-проекте заикнетесь про RIIR всего подряд, вашему руководству это вряд ли понравится), а также отлаживать интероп в случае необходимости. В идеале хорошо бы изучить ещё и ассемблер, если в ваши задачи входит написание высокопроизводительного кода — вам придётся периодически пялиться в asm output, понимать, что там происходит и что там "не совсем так".

                    +4

                    У нас на работе у парочки джунов Rust — первый язык. У нас RIIR во все щели, мы им даем переписывать сишные утилиты. С они не знают, читают код чисто семантически, без понимания тонкостей всех приседаний. А для оберток и интеропа надо уметь читать. И то, не С, а документацию.

                      0
                      Ну для обучения переписывать небольшие сишные утилиты, руководствуясь «пролетарским классовым чутьем» — это нормально. Другое дело, когда вам придется взаимодействовать с большими сторонними библиотеками, которые вы не сможете переписать силами пары джунов. А третье — когда вам придется всю эту связку еще и отлаживать. Одного умения читать документацию (которая к тому же бывает разного качества) может не хватить, а пока вы будете дергать upstream библиотеки на предмет «вылечите баг по симптомам», процесс разработки будет стоять. Upstream'ы, кстати, вообще предпочитают, когда им присылают сразу патчи. Впрочем, дело хозяйское.
                    +4

                    Есть и другие варианты подстановки. Но с частью до второго слеша я полностью согласен.

                  +6

                  Вот бы на собеседовании в Яндексе был вопрос про while do и ты такой — "ну вот представьте, есть в холодильнике торт… "

                    +5
                    Умение объяснить сложную вещь простыми словами всегда в цене.
                    Другое дело, что про while знают почти все, а вот когда нужно новичку за десять минут объяснить устройство сложной продакшен-архитектуры — тут и аналогия с тортиками подойдёт :)
                      0
                      Вот и мне тоже стало интересно, без холодильника эти студенты с циклами смогут работать?)
                      +7
                      По теме, могу порекомендовать отличный доклад Kate Gregory под названием «Stop Teaching C», основная мысль которого: перед освоением C++ вовсе нет нужды в обязательном порядке сначала обучать студентов C, а если вы это делаете, то четко разграничивайте и объясняйте разницу между «C++» и «C с классами».
                        +2

                        Спасибо! Доклад правда очень хорош, мы им вдохновлялись ещё при разработке «Белого пояса» на Курсере.

                        +1
                        Знакомый недавно пошел на этот самый курс и вскоре попросил помощи. Дескать задача совсем простая, но он не понимает что не работает.
                        Суть задачи — даются два вещественных числа и нужно написать равны ли они, а если не равны, то их разницу.
                        Показывает свое решение — код прошел 10 тестов из 31. Смотрю на код — вроде все верно. Если равны, то сообщение; если одно число больше, то вычитаем из большего меньшее.
                        В логике ошибок не вижу. Говорит, что причины ошибок указаны такие:
                        Вы не считаете размер половинок вещественным числом
                        Вы неправильно обрабатываете случай, когда первая часть больше
                        Вы неправильно обрабатываете случай, когда первая часть меньше

                        В результате оказалось, что товарищ в коде делал:
                        cout << to_string(a-b); // выведет, например «0.900000»
                        А надо было:
                        cout << a-b; // выведет, «0.9».
                        Говорит, что вроде в лекциях упоминали или использовали именно to_string. Про точность в ответе в задаче я не увидел.
                        Учитывая, что ситуация один-в-один гуглится прям сразу, то выглядит это не хорошо. Особенно для одной из первых задач.
                        За исключением этого момента курс хвалил, но опять же занимается еще не долго, посмотрим, что скажет в конце.
                          0

                          Это явный баг, поправим.

                            +3
                            У С++ на Яндекс Практике пока очень много проблем.
                            1) Рваное повествование, зачастую блоки не связаны с друг другом и повествование очень поверхностное и постоянно прыгает в разные темы и обратно, но радует что хоть и поверхностно но все необходимые темы затронуты.
                            2) Очень много ошибок в тренажере.
                            3) Очень долго отвечает поддержка и не в тему часто.
                            4) Очень мало времени с преподавателем, всего один час за 2 недели, а все остальное время как хочешь так и выкручивайся ищи и читай сам, иногда именно немного и не сразу помогает наставник или студенты. Например в других местах каждое занятие проводит учитель и проверяет так же учитель с которым можно что то обсудить в отличие от тестов.
                            5) Основной проект всего курса строго фиксированный и с сильно навязанным кодом, если с чем то не согласен то нет возможности внести изменения, так как проверяет выходную работу каждого спринта с начала автоматический тест, который ни кто переписывать не собирается. Например учат что существует только одна кодировка ASCII и что символы выше 127 не обрабатываются и в коде спокойно не используются cctype а берется прямо c >= '\0' && c < ' '; Хотя на самом деле существует множество кодировок и даже если ограничиться ASCII то символ 127 \x7F \177 backspace character (DEL) обрабатывается как обычная буква.
                            6) Нет возможности выбирать себе нагрузку. Например нельзя параллельно выбирать себе еще темы если есть свободное время(но есть небольшой раздел с заданиями не относящимися к темам курса, где можно что то порешать совместно). Весь курс разбит на жесткие спринты и дедлайны. Например в других местах есть возможность брать несколько направлений одновременно, если есть возможность заниматься больше времени.
                            И еще много проблем с которыми нужно работать.
                            Но в целом это лучший курс который можно найти в российском интернете, в других местах нет такого размаха интересных и актуальных тем по C++
                              +2

                              Спасибо за фидбек.


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


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

                                +1
                                5 пункт, вы прям совсем хардкор описали. Я когда заходил посмотреть курс, столкнулся с куда более тривиальными проблемаи:
                                Сначала дают нотацию, всегда заврешать с «endl», а потом сами же ее и нарушают, так, что ни один тест в задании не проходит. (проверил, испраивли, теперь принимает и с и без «endl»)
                                Дальше некоторые задачки с оч скудными условиями. В том же 3 уроке, про for всё оч неочеивдно, и вроде логично на реагировать на лог и дополнять условия (брутфорсим вместо внятной поставленой задачи), но доходит до того, что лог никаких ошибок не выдает кроме как «Задача прошла 14/15 проверок» — называется побудь экстрасенсом. (проверил, с июля единственное изменение — выдает «Задача прошла 15/16 проверок»)
                                Тех поддержка не то что долгая, а для нее практикум как побочка, просто в доп нагрузку. По началу отписки вместо ответов. И скорее пришлют готовый ответ (код), чем дадут на тесты глянуть (точнее без «скорее», так и сказали что тесты показать не могут).
                            +2
                            Давно хочу попробовать такой подход в обучении с++. Но все думаю о такой проблеме. Вот вы учите новому с++, а тут студент начинает гуглить, а в интернете (да и в книжках) большинство примеров чего-либо написаны как раз на старом Си с классами.
                            Что ему делать в таком случае? Или на практике все не так плохо?
                              +4

                              Ваши сомнения отчасти оправданы: студентам всё же придётся узнать про new и delete; не только для понимания внутреннего устройства контейнеров, но и для чтения страшного кода.
                              Но я считаю, что не так всё и страшно, чтобы готовить к этому с самого начала. Гугление может привести как к старому коду, так и к смелому эксперименту с C++23. Поэтому в числе прочего важно научить, скажем, смотреть в нужное место на cppreference вместо рандомных поисковых запросов.

                                +3

                                Я своим на каждую тему рассказываю: вот вы будете её гуглить, вам будет выпадать такая-то и такая-то фигня (гуглю самостоятельно перед лекцией), вот её читать не надо потому и потому.


                                Например, если вам в теме "наследование" вам начинают рассказывать, что яблоко наследуется от фрукта, а вентилятор — от электрического двигателя, и вы не понимаете, почему их игрушечный пример без виртуальных функций хоть какое-то отношение к реальности имеет — это нормально, никакого не имеет. Или если где-то написано iostream.h/conio.h — бегите оттуда. А вот ISO C++ FAQ и cppreference читать как раз можно и нужно тренироваться.

                                0
                                Не попадайте в ловушку джокера, не учите ни си ни плюсы ни си с классами
                                  +13

                                  … ни вообще все это программирование.

                                  +13

                                  У меня к вам вопрос, а как вы учите студентов пользоваться вектором правильно. В моём мире 100% людей работающих с плюсами (и даже сеньоры) иногда да возьмут да и сохранят указатель/ссылку на элемент вектора, а потом возьмут да и добавят новый элемент в вектор, а потом поработают с ссылкой. Я думаю для вас не секрет, что это довольно часто нормально сработает, но вот иногда все будет печально. Так вот как ваши студенты воспринимают первые встречи с УБ и как вы их учите с ними справляться? Учить с++ и не учить как жить в мире с УБ это пустая трата времени и вашего и студентов, а потом ещё и того парня который будет это все чинить.

                                    +5

                                    Не автор, но отвечу: на первой же лекции минут 15-30 посвящается UB и вбиванию в головы запрета на мышление "тут ошибка, но очевидно же, что компилятор поведёт себя так и так" с кучей интерактивных примеров под разными ОС и компиляторами, сравнением с другими языками и фразой про то, почему так.


                                    И дальше регулярно напоминаю каждый раз, когда возникает очередное UB, что нельзя полагаться, что оно проявится ровно таким образом, и что программа может упасть вообще через пять минут в другом месте.


                                    Как ловить — показываю санитайзеры, Valgrind, статический анализ (предупреждения компилятора, clang-tidy, cppcheck), обязательная компиляция под разными компиляторами. Это, разумеется, всё равно покрывает далеко не всё, так что на лекциях регулярно всплывают UB, которые вообще никем не ловятся и молча ломают программу. Иногда. А иногда не ломают. Типичный пример — static initialization order fiasco.


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

                                      +2
                                      Ну если это правда, а у меня нет причин не верить, тогда сразу +100 к качеству курса. Может ещё расскажите, что помимо того, что вы учите студентов писать с++ код (что в общем то не рокет сайнс) вы ещё и ЧИТАТЬ с++ код учите?

                                      Что я имею ввиду ?- упражнение типа перечислите все ошибки, которые вы можете найти в таком то продакшн учебном коде. Я бы это вообще частью выпускного экзамена сделал, на бумажке (т.к. на код ревью в реальности нет доступа ни к исходникам ни к IDE). Если нашёл меньше минимального количества багов — сразу просто незачёт не взирая ни на что другое.

                                      Есть ещё один навык который я называю умением читать код — перед тем как копипастить со стэка писать свой велосипед нужно сначала поискать, а что уже есть в стандартной библиотеке и/или другом фрэймворке который используется в проекте и наконец у каждого большого проекта есть своя библиотека типа Tools/всякое_полезное и там почти всегда как с попаданием в кэш уже можно найти готовый к употреблению код.

                                      Ну и самое частое люди обычно находят место в коде куда нужно добавить новый функционал и прямо туда его и фигачат сплошной простыней, а то что используются разные уровни абстракции вообще ни каких сомнений не вызывает. Вот пример для наглядности
                                      void implementLotsOfLogicHere()
                                      {
                                      DoHighLevelA();
                                      DoHighLevelB();

                                      // new code added here
                                      Container anotherViewOnTheData;
                                      while (x: container)
                                      {
                                      if(x == ...)
                                      {
                                      anotherViewOnTheData.push_back( Y{ x } );
                                      }
                                      }
                                      callback(anotherViewOnTheData);

                                      // previous code conitnue
                                      DoHighLevelC();
                                      }

                                      И это еще идеально если DoHighLevelX кто-то уже написал, а в реальности там вместо этих функций тоже смесь кода с разной степенью абстракции — в одной строчке зарождение вселенной, а рядом байтики копируется в цикле из одного вектора в другой.

                                      Если вы еще и читать код ваших студентов учите, то это прямо вообще респект и уважуха.
                                        +3

                                        Ваш комментарий содержит уйму полезных и важных идей.
                                        Про часть из них уверенно скажу, что да, учим. Во второй половине курса есть тема (вот прямо сейчас делаем) про красоту кода, читаемость, масштабируемость и работу с чужим кодом. И одна из задач там — взять чужой сложный код, доработать его под себя и отдать на ревью. Другая задача — взять небольшую чужую библиотеку и приспособить её под нужды своего большого проекта. И тоже отдать на ревью.
                                        Простите за рекламу, но наличие на курсе ревьюеров — это заметное преимущество Практикума перед Курсерой. К слову, я сам в своё время учил C++, проводя ревью студентов :)

                                          +4

                                          У вас похоже действительно годный курс. У меня есть пара пожеланий, пожалуйста не продвигайте использование shared_ptr и любой другой инкарнации — это просто ад, большинство девелоперов в независимости от их опыта имеют ложные ожидания при использовании шаредных указателей, в реальном мире люди ожидают предопределенный порядок вызова деструкторов в многопоточном коде который шарит указатель. Это проблема номер 2, а проблема номер 1 и вообще ошибка на миллиард это деструкторы — опаснее кода в с++ не найти. Колл стэк значительно более половины всех крашей содержит вызов хотя бы одного деструктора. Так хохмы ради проведите опрос среди ваших сеньоров и спросите, а какой код в деструкторы НЕ УБ, т.к. примерно 146% кода в дестукторах из реального мира содержит хотя бы одно уб. Для проверки истинности ответа рекомендую либо стандарт либо тоже самое, но для людей cppreference. Самое печальное обе проблемы поставляются в комплекте.

                                            0
                                            Ну про shared_ptr рассказывать все равно надо. Если не они, то кто-нибудь другой расскажет. А с деструкторами, да, беда. Нужно сильнее вдалбливать в людей идею RAII и самое главное объяснять что далеко не любой деструктор это RAII
                                              0
                                              самое главное объяснять что далеко не любой деструктор это RAII

                                              Это вы про что?

                                                0
                                                RAII — «Получение ресурса есть инициализация». Но далеко не всегда мы получаем именно ресурс. То есть, если мы написали какой-то код в деструкторе, то очень редко этот код связан с каким-то ресурсом.
                                                Ресурсом может быть память (new — выделили, delete — освободили), файл (open — открыли, close — закрыли). Да и то насчет файла уже можно поспорить. Особо больше новых ресурсов и не придумать даже. Почти все остальные сущности в программе ресурсом не являются (ну по крайней мере, в тех программах, где слишком много деструкторов)
                                          0
                                          (т.к. на код ревью в реальности нет доступа ни к исходникам ни к IDE)


                                          На CodeReview есть (и должен быть) доступ и к исходникам и к IDE.

                                          Другое дело, что на практике: если тебе пришлось выкачивать ветку, чтобы разобраться что же CodeReview делает — это признак что в процессе что-то не так (да может быть это сложная задача в сложной предметной области, но на каждую такую «необходимую» сложную задачу приходится несколько где человек просто поленился нормально разбить свои правки).

                                        +2
                                        На курсере ребята довольно подробно объясняли инвалидацию ссылок/указателей/итераторов и показывали на примерах для разных std контейнеров, за что им респект :) Наверняка и в Практикум это завезли.
                                          +1

                                          Завезли :) Это не в самом-самом начале, но довольно рано.
                                          А при первом знакомстве с вектором показываем, что при выходе за границы вас не поймают за руку — и это плата за эффективность.

                                            0
                                            А при первом знакомстве с вектором показываем, что при выходе за границы вас не поймают за руку — и это плата за эффективность.

                                            Это та самая плата, которая даёт дай бог один процент оверхеда в подавляющем большинстве приложений?

                                              0
                                              1% оверхеда на кластере — это сотни тысяч долларов
                                                –1
                                                А данные про один процент оверхеда будут? Или тут нужно просто поверить?
                                          +4
                                          C++ изучать, во-первых, поздно. А во-вторых — это не самый стройный и органичный язык. Компромисс между возможностями железа 40 лет назад и представлениями того времени о, как теперь оказалось, переоценённом ООП. Эдакое древнее здание с земляным полом и кучей хаотичных пристроек более поздних годов.
                                          А какой язык стоит изучать? А не знаю, мы дошли до того, что теперь нет единого стандарта на компилируемый язык программирования.
                                            +1
                                            А какой язык стоит изучать? А не знаю, мы дошли до того, что теперь нет единого стандарта на компилируемый язык программирования.

                                            ИМХО стоит изучать несколько языков, чтобы представлять спектр возможностей. Ну там, C++ для низкоуровневой ерунды и чтобы представлять, как не надо делать метапрограммирование, Rust для более типобезопасной низкоуровневой ерунды, Haskell для функциональщины и какой-нибудь Idris для хардкорного упарывания типами.

                                              +1

                                              А так ли оно плохо, это метапрограммирование в с++?
                                              Покажите мне другой язык который умеет то-же самое без привлечения рантайма и с прогнозируемыми накладными расходами? Раст обещал доступ к AST стабилизировать еще до версии 1.0, одноко продвинулись они пока не сильно.

                                                +2

                                                Haskell с его, собственно, Template Haskell. Накладные расходы в рантайме нулевые. В компилтайме можно выполнять любой код из любой библиотеки — можно хоть какой-нибудь алгоритм на графах из библиотеки, ничего не знающей про TH, взять, можно хоть пойти на сервер и взять XSD со схемой, а потом по ней сгенерить типы и функции для общения по этой схеме.


                                                Совсем упарываться — любой язык с зависимыми типами и инструментами для гарантии стирания типов (coq со стиранием в Prop, idris с quantitative type theory, позволяющей помечать аргументы как иррелевантные в рантайме, agda с похожей концепцией runtime irrelevance).

                                                  0
                                                  А почему, кстати, Haskell не имеет почти никакого коммерческого применения?
                                                    +2

                                                    А почему он не имеет? Как-то вполне имеет, ИМХО. Я как раз вот прям сейчас мозгую, на какой из двух офферов соглашаться, в обоих из которых порядком хаскеля. При этом эти компании я не искал, они почти что сами меня нашли.


                                                    Ну и я вполне использовал хаскель в продакшене даже тогда, когда моя официальная лычка была «senior c++ engineer».

                                                      0

                                                      Вы вроде какой-то исследовательский проект пилили за спасибо? Похоже деньги заканчиваются, а спасибо чето не очень вкусное и надо идти добывать масло на хлеб. Я бы тоже хотел свой "Раст" запилить, но… Подожду маленько. Вы хоть "отчёт" о своем исследовании опубликуйте, а то и непонятно "стоило" оно того или нет, понятное дело что вам в кайф, но нам то со стороны виднее.

                                                        +1
                                                        Вы вроде какой-то исследовательский проект пилили за спасибо? Похоже деньги заканчиваются, а спасибо чето не очень вкусное и надо идти добывать масло на хлеб.

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


                                                        Вы хоть "отчёт" о своем исследовании опубликуйте, а то и непонятно "стоило" оно того или нет, понятное дело что вам в кайф, но нам то со стороны виднее.

                                                        Не уверен, что из этого получится хабровский формат. Там слишком много технических деталей, которые будут интересны довольно узкому кругу людей (например, последние 4-5 месяцев я тупо потратил на формализацию куска работы, и формализовал где-то от трети до половины всего, что нужно).


                                                        Впрочем, оно всё в опенсорсе, и, в частности, даже гитхабовский CI собирает периодически свежие версии статьи-описания (там черновик пока, правда, и его ещё допиливать надо, но идея понятна, вроде как). Так что можно как-то что-то посмотреть.

                                                          +2

                                                          Половины матерных слов из вашей статьи я не понимаю за не именем соответствующего бэкграунда, но суть мне вроде бы далась. Было бы интересно почитать в переводе на простой и понятный программистский язык. Примеры в ведении были очень хороши и рассказали мне больше чем вся остальная часть. Скажу сразу, что всю мякотку с лемами теоремами и корректностью я даже не пытался осилить. Мне нравится идея жидких типов, но мне это интересно только с точки зрения как это реализовать. Меня вполне устроит знать, что где то кто-то доказал, что это не чушь суть доказательства меня не волнует. Не могли бы вы подсказать где найти код/описание как реализовать эти типы, на каком нибудь народном языке, а не на вашем птичьем агдесе, в котором вот честно вообще нихера не понять.

                                                            0
                                                            Не могли бы вы подсказать где найти код/описание как реализовать эти типы, на каком нибудь народном языке, а не на вашем птичьем агдесе, в котором вот честно вообще нихера не понять.

                                                            Если реализовать — вы же первым будете возмущаться, фигли тут так много кода и вообще так всё сложно навёрнуто.

                                                              0
                                                              Скажу сразу, что всю мякотку с лемами теоремами и корректностью я даже не пытался осилить. Мне нравится идея жидких типов, но мне это интересно только с точки зрения как это реализовать. Меня вполне устроит знать, что где то кто-то доказал, что это не чушь суть доказательства меня не волнует.

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


                                                              Не могли бы вы подсказать где найти код/описание как реализовать эти типы, на каком нибудь народном языке, а не на вашем птичьем агдесе, в котором вот честно вообще нихера не понять.

                                                              Там в папке toy заготовка (которую я, впрочем, забросил и в обозримом будущем к которой не вернусь).

                                                                0

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

                                                                  0
                                                                  > то нашёл три дырки в чужих системах типов
                                                                  А где и как были описаны эти системы типов?
                                                                    0

                                                                    В виде таких же статей (только где-то опубликованных, а не черновиков), и в виде таких же диаграмм.


                                                                    Только они не занимались формализацией своих систем на всяких агдах-коках, а дъявол, как известно, в деталях, которые в доказательствах на бумаге часто заметаются под «Доказательство очевидной индукцией ∎»

                                                        0

                                                        Справедливости ради — GHCi рантайм TH не отменяет, про остальные не в курсе как они работают, но подозреваю что там та же история с VM внутри, а это не честное сравнение.
                                                        Трудно сказать реализовано TH делает мета-программирование как то принципиально лучше чем C++, тут скорее вопрос что высыпается в консоль когда в шаблонах ошибка. Скорее всего что-то более удобоваримое чем из c++98, а вот с кодом на концептах сравние уже интереснее звучит.

                                                          +2
                                                          Справедливости ради — GHCi рантайм TH не отменяет, про остальные не в курсе как они работают, но подозреваю что там та же история с VM внутри, а это не честное сравнение.

                                                          Я не понял эту фразу. ghci — это репл, нужный для быстрых экспериментов или быстрой проверки, что код всё ещё тайпчекается. ghc без i на конце выдаёт после компиляции нативный код без каких-либо VM внутри.


                                                          Трудно сказать реализовано TH делает мета-программирование как то принципиально лучше чем C++, тут скорее вопрос что высыпается в консоль когда в шаблонах ошибка. Скорее всего что-то более удобоваримое чем из c++98, а вот с кодом на концептах сравние уже интереснее звучит.

                                                          Ну вот когда на C++ в компилтайме можно будет взять какой-нибудь nlohmann json, прочитать жсон с диска, распарсить его этим nlohmann'ом и сгенерировать какие-нибудь классы (или, обратно, взять какие-нибудь классы, по ним нагенерить данных и сериализовать в жсончик nlohmann'ом), то тогда можно будет сравнивать.

                                                            –1

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


                                                            Касательно второго примера -это кодогенерация а не мета программирование.

                                                              +1

                                                              Любое метапрограммирование (то есть, преобразование AST в другое AST) может быть заменено кодогенерацией. Вопрос в том, можно ли обойтись без кодогенерации, и насколько удобно это сделать.


                                                              А то в плюсовом мире уже лет 25 как есть moc, например.

                                                                0
                                                                Тут вы путаете, никакое преобразование AST -> AST вам не позволит «прочитать жсон с диска, распарсить его этим nlohmann'ом и сгенерировать какие-нибудь классы».
                                                                В свою очередь кодогенерация не прибита к AST а значит сгенерировать что то под конкретные вызовы функций не получится. В этом плане TH крут как раз тем что он совмещает эти концепции, и можно написать шаблон в духе «если передана функция от 2х аргументов скачай json с интернета»

                                                                moc это не валидный аргумент, moc завезли во времена когда поддержка мета-программирования популярными на тот момент компиляторами была «не очень». В современном С++ от moc можно избавиться, но т.к. его синтаксис не соответсвует принятому в С++ придётся все эти мета-определения переписывать, а бизнес не очень любит переписывать, так что moc остаётся.
                                                                  0
                                                                  Тут вы путаете, никакое преобразование AST -> AST вам не позволит «прочитать жсон с диска, распарсить его этим nlohmann'ом и сгенерировать какие-нибудь классы».

                                                                  Позволит, если язык, на котором описываются преобразования, достаточно мощен. В случае TH это весь хаскель, включая все имеющиеся библиотеки (с малыми оговорками), в том числе, про TH ничего не знающие. Не нужно никаких constexpr/consteval.


                                                                  В свою очередь кодогенерация не прибита к AST а значит сгенерировать что то под конкретные вызовы функций не получится.

                                                                  Почему? Берёте libclang условный, парсите ваш условный код на плюсах и генерируете что угодно.


                                                                  В современном С++ от moc можно избавиться,

                                                                  Как? Без макросов только.

                                                                    0
                                                                    Позволит, если язык, на котором описываются преобразования, достаточно мощен.

                                                                    Язык тут не причем, можно парсинг джсона и на шаблонах c++ написать, но компилятор не позволяет вам читать файлы во время компиляции.


                                                                    Берёте libclang…

                                                                    Так можно и парсилку джсона из вашего примера сделать, к языку C++ это отношение не имеет.


                                                                    Как? Без макросов только

                                                                    С макросами, т.к. это единственный способ получить одновременно и имя символа и его строковое представление (нужно для мок объекта), но макросы это часть языка описанная в стандарте. Все еще интересно?

                                                                      +2
                                                                      Язык тут не причем, можно парсинг джсона и на шаблонах c++ написать

                                                                      А в хаскеле — не нужно ничего на шаблонах писать. Я просто могу взять ту же самую либу, которую я использую для парсинга жсона в рантайме, и выполнить её код в компилтайме. Metaprogramming done right.


                                                                      но компилятор не позволяет вам читать файлы во время компиляции.

                                                                      А в хаскеле — позволит. Я просто беру обычную функцию readFile и вызываю её во время компиляции. Например. Или у меня на одной прошлой работе была библиотека, которая брала XSD-схему с диска (я тот пример не просто так придумал) и генерила по ней кучу всяких типов вместе с эффективными сериализаторами-десериализаторами.


                                                                      Более того, в хаскеле можно, например, в компилтайме распарсить строку с шаблоном ассемблерного кода, сделать над ней какие-то преобразования, а потом определить функцию, которая выполняет этот ассемблерный код. Я даже соответствующий proof-of-concept-пакет сделал, почитайте вот ридмишку.


                                                                      Так можно и парсилку джсона из вашего примера сделать, к языку C++ это отношение не имеет.

                                                                      Можно. Только я бы предпочёл её делать на тех же плюсах, и не наворачивать сложности в процессе сборки.


                                                                      С макросами, т.к. это единственный способ получить одновременно и имя символа и его строковое представление (нужно для мок объекта), но макросы это часть языка описанная в стандарте. Все еще интересно?

                                                                      Да с макросами понятно. Но макросы к C++ прикручены настолько сбоку, что от кодогенерации внешними инструментами они не сильно отличаются.

                                                                        +1
                                                                        Скажите, если знаете/обоснованно предполагаете, а насколько сложно взять условный шланг и запилить в нем «беру обычную функцию readFile и вызываю её во время компиляции» ну скажем для плюсов или раста? Я знаю такое почти работает в D, там в компайл тайме много чего можно сгенерить по строковым литералам, но по моему «readFile и вызываю её во время компиляции» для зачитывания этих строк пока не сделано.
                                                                          0

                                                                          Ну, по крайней мере, пропозалы есть. Вроде где-то даже были реализации — если начать гуглить по ключевым словам из таблички в 5.1.1 (по phd::embed, в частности), то что-то нагугливается. Объём патчей и сложность реализации я не смотрел.


                                                                          Но, опять же, это какие-то костыли, для добавления которых требуются пропозалы. Нельзя просто взять std::ifstream и дёрнуть его на этапе компиляции.

                                                                            0

                                                                            Да я почитал проползал, это вообще ни о том. Я имел ввиду выполнение произвольного кода на с++ как часть компиляции произвольного кода на с++. Я так понимаю это то что умеет хаскель. Что то мне подсказывает для этого интерпретатор с++ должен быть встроен в компилятор или есть другие подходы к этому? Т.е. сложность задачи сводиться к созданию интерпретатора.

                                                                              +1

                                                                              Интерпретатор уже есть: иначе constexpr-функции никак не реализовать.

                                                                            0

                                                                            На практике нет ничего сложного получить содержимое файла для компиляции — берем условный bin2c, и добавляем его вызов в систему сборки.
                                                                            Другое дело — выполнить условный fopen во время компиляции — тут надо и окружение c++ запустить, и слинковаться, и разрулить как то глобальные переменные. А теперь представьте что это все происходит в кросс-компиляторе, и объявление того же fopen не совпадает с системным, и например нужна еще другая пачка дефайнов.

                                                                          0
                                                                          но компилятор не позволяет вам читать файлы во время компиляции.

                                                                          #include «data.json»
                                                        +4
                                                        C++ изучать, во-первых, поздно

                                                        Напомнило, как Остап Бендер бегал по киностудии, пытаясь продать свой сценарий и ему отвечали, что он не подходит для немого кино, так как его уже нет и не подходит для звукового кино, так как его ещё нет. Так и тут — плюсов, оказывается, уже нет, но на их месте тоже пока ещё ничего нет. Ни Rust, ни Go не заняли нишу, а писать всякие там операционки, базы данных и браузеры на чём-то надо.
                                                          +1
                                                          И почему-то всякие там операционки до сих пор пишутся на си без плюсов. Странно, да?
                                                            +4

                                                            Потому что легаси. Когда начинали писать большинство ядер современных ОС, C++ ещё только начинал захватывать мир, был сыроват, не имел кучи вещей, которые имеет сегодня, а возможности железа заставляли экономить выделение каждого байта. Ну, а в Linux например во главе разработки вообще стоит благородный диктатор Линус, отношение которого к C++ он сам описывал как «А просто не нравится и всё» без каких-либо существенных аргументов (а те, что звучали, навевают мысль о том что он просто хейтит то что не умеет нормально готовить) и с ним уже давно все расхотели спорить.
                                                            Есть и контр-примеры ядер ОС на C++, например EPOC32 и Symbian, которые прекрасно работали на устройствах с дохлыми процессорами и крохотной памятью, а ещё BeOS (и ее наследница Haiku). Все они были отличными ОС в техническом плане и умерли исключительно из-за факапов менеджмента. Ещё можно назвать ряд микроядер L4 (вариацию NICTA которого Qualcomm использует в своих чипах для телефонов), ну и частично ядро Zircon, которое Google пилит для своей новой Fuchsia.


                                                            А вот огромное количество довольно сложного и критичного к производительности софта типа графических движков AAA-игр никому в голову не придет писать на Си вместо C++ в наше время. Вполне очевидно, почему.

                                                            –1
                                                            И почему-то всякие там операционки до сих пор пишутся на си без плюсов. Странно, да?

                                                            Ядра, но не юзерспейс. Вот код терминала Windows, вод код калькулятора Windows — это всё плюсы.

                                                            А у ядра огромное использование. Даже плюс одна инструкция к коду вызова какой-нибудь функции выделения памяти или переключения потоков — это какие-то невероятные цифры потерь в мировом масштабе, учитывая распространённость ОС и количество вызовов подобных функций каждую секунду.
                                                              +3

                                                              Только на плюсах можно написать ещё более эффективный код чем на Си.

                                                                0
                                                                Правда? А чем это обусловлено?
                                                                  0

                                                                  Я говорю в контексте ядра ОС.


                                                                  C++ поддерживает почти весь синтаксис Си, а его компилятор столь же эффективен на Си подмножестве (да и обычно это один и тот же компилятор). А так как С++ более развит, есть места где его компилятор может лучше оптимизировать код.


                                                                  Это конечно если не ударяться в создание фабрики фабрик классов и не обмазываться стандартной библитекой.

                                                                    +1

                                                                    Метапрограммировать на темплейтах проще, чем на макросах.

                                                                      +2
                                                                      макросы vs метапрограммирование, которое позволяет инстанцировать (подставить в зависимости от шаблона) реализацию для конкретных типов, а не для (..., char *elem, size_t elem_size).

                                                                      ПС
                                                                      А уж как интересно, когда у вас в C-структуре есть паддинг (заполненный мусором) и вы считаете одинаковые элементы разными ;)

                                                                  +1

                                                                  Тут мне кажется есть несколько оснований:


                                                                  1. Легаси.
                                                                  2. Зачем что-то переписывать? Существующие ОС не развиваются прям семимильными шагами, что новый код приходит тоннами. Си на минималках знают все, соответсвенно и патчи прислать могут и т.д.
                                                                  3. Нет специалистов. Ну нет столько людей, которые одновременно знают и умеют в планировщики/ФС/драйвера и т.д., и при этом, являются фанатами С++/rust/haskell и вообще языковой темой.
                                                                  4. Си — это основа основ. Это то, что лежит поверх железа и предоставляет минимальный API/ABI. И даже если ядро ОС будет написано на С++/Rust, то оно будет предоставлять тупые сисколы которые идеально будут соответсвовать Си. Да и вообще Сишное ABI — это стандарт для взаимодействия между разными языками.
                                                              0
                                                              A cheatsheet of modern C++ language and library features.
                                                              github.com/AnthonyCalandra/modern-cpp-features
                                                                +2
                                                                Блин, в наше время после программирования на ассемблере C++ казался божественным языком. Может стоит так делать и сейчас?
                                                                  +6

                                                                  Хочешь сделать человеку хорошо? Сделай сначала плохо, а потом верни как было.

                                                                  +3
                                                                  Может и плохо прочитал статью, но не нашёл упоминания про code style
                                                                  Стараюсь студентов сразу приучать к осмысленному именованию переменных, обговариваем с ними о соглашении как хорошо писать и как плохо писать код, нормы оформления.
                                                                  Считаю этот момент тоже важным при обучении программированию.
                                                                    +2

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

                                                                      +2
                                                                      Тогда отлично!
                                                                      –1
                                                                      Programming is a creative art form based in logic. Every programmer is different and will code differently. Do not waste your time on coding style it is the output that matters. John Romero. Я считаю так же, что навязывать стиль кода это очень плохо так как это убивает креативность, но убедить в той или иной технике это возможно, при условии того что человек может и не соглашаться с доводами и сам решать как он форматирует свой код. Так же такие жесткие рамки приводят к ужасным и деспотичным перекосам. Вот пример кодстиля из одной крупной Российской компании(обратите внимание на пункт 3):
                                                                      1. Размер единичного отступа составляет 2 пробела. Для форматирования кода не используются символы табуляции.
                                                                      2. Фигурные скобки {} располагаются на отдельной строке и имеют тот же отступ, что и соответствующий им заголовок функционального блока — декларация функции либо условие if / switch / for / while.
                                                                      3. Параметры функций располагаются на отдельной строке, имеют префикс _и предваряются двойным отступом относительно заголовка функции.
                                                                      4. Отсутствие в коде неиспользуемого функционала (выражений либо переменных, закомментированных участков устаревшего или отладочного кода)
                                                                        +4
                                                                        Форматирование — это только часть Code style. Туда ещё входит адекватное именование переменных, отсутствие переусложненных конструкций, отсутствие функций по 300 строк и т.п.

                                                                        Имхо вот как раз форматирование кода не имеет с креативностью вообще ничего общего. И правила форматирования должны быть зафиксированы, но так, чтобы о них не думать от слова совсем (ну то есть использовать автоформаттеры).
                                                                          +1
                                                                          С перекосами согласен.
                                                                          А вот с тем, что каждый пишет код как хочет и не придерживается единого стиля — не соглашусь. Разработка одиночками ушла немного в прошлое. Сейчас всё больше работа в команде. Поэтому нужно вырабатывать в командах единые правила, иначе будет сложно собирать единый код из разных кусочков.
                                                                            0
                                                                            Грамотно установленные правила форматирования кода понижают вероятность ошибок по невнимательности (от которых не застрахован никто, вообще никто). Особенно те, что относятся к комментариям, выравниванию кода, обязательным {} даже для однострочных блоков, скобок в условиях, и т.д.

                                                                            (точно так же как и -Wextra -Wpedantic -Wall -Werror могут спасти от многих часов головной боли).

                                                                            А что до мелочей, типа количества табов/пробелов и переносов скобок после сигнатур, то никто не запрещает вам при большом желании написать свой конфиг для .clang-format и настроить post-checkout и pre-commit хуки в Git, чтобы у вас в редакторе код выглядел так, как нравится вам, а в общей репе соответствовал установленному в команде стандарту.
                                                                          –1
                                                                          Linus Torvalds: “C++ is a horrible language. It’s made more horrible by the fact that a lot of substandard programmers use it, to the point where it’s much much easier to generate total and utter crap with it. Quite frankly, even if the choice of C were to do *nothing* but keep the C++ programmers out, that in itself would be a huge reason to use C.”

                                                                            –1
                                                                            LOL… Торвальдса заминусовали на Хабре…
                                                                              +1
                                                                              Цитата вырвана из кучи контекстов.

                                                                              Во-первых, это было в 2007 году, за 4 года до выхода стандарта С++11, а значит относилось к С++ версии 1998 года(!). Трудно не согласиться с тем, что это был ужасный язык.

                                                                              Во-вторых, это был ответ на письмо, которое начиналось вот так: «When I first looked at Git source code two things struck me as odd 1. Pure C as opposed to C++. No idea why. Please don't talk about portability, it's BS.». Что он должен был ответить человеку, который начинает разговор с фразы «твой код — дерьмо, потому что не С++»?

                                                                              Ну и в третьих, это был разговор с программером из Microsoft, идеологическим, так сказать, врагом (ну по крайней мере так это выглядело в 2007 году).
                                                                                –2
                                                                                Знаете, я не хочу устраивать тут длинную дискуссию про контексты. Но от того, что этому монстру немного обновили фасад с 1998 года, он, увы, не стал образцом архитектуры, достойным изучения в университетах.
                                                                                  0
                                                                                  У вас какие-то забавные представления об окружающей действительности. Языки изучают не потому, что они являются каким-то «образцом архитектуры», а потому, что на них написана куча кода, который нужно поддерживать, развивать, писать новый и стыковать старый код с новым кодом. Чисто «академические» языки же типа Хаскеля (да простит меня deadfood) или Пролога (преподносившегося как next-gen в свое время) прозябают в безвестности.
                                                                                    0
                                                                                    И тем ни менее, его там изучают :)
                                                                                    +1

                                                                                    Справедливости ради, там всё-таки заявление, что "Мне кажется странным, что тут Си вместо плюсов. Почему? И нет, не говорите про проблемы с переносимостью, это бред.". Или я чего-то не понимаю?


                                                                                    От себя: сама цитата в основном про то, что у плюсов ниже порог вхождения, что приводит (по мнению Линуса) к более низкому качеству контрибуций от тех, кто пишет на нём. К самому языку там претензий, кроме как "на нём проще писать лютую хрень, чем на Си", не высказывается.

                                                                                +1
                                                                                >
                                                                                Внутрь цикла while надо добавить: «откусить кусок торта; отойти от холодильника» — иначе, если в холодильнике есть торт, цикл бесконечный
                                                                                  0

                                                                                  О обучении есть 2 подхода:


                                                                                  1. Вы рассказываете теорию, а потом ставите задачу для проверки усвоения.
                                                                                  2. Вы ставите задачу и подсказываете обучающемуся что надо изучить для решения этой задачи.

                                                                                  2-й подход более эффективен но требует другой инфраструктуры. Сразу нужны и книги и оборудование/наглядный материал. По этому практически везде используется не особо эффективный 1-й подход.

                                                                                    0
                                                                                    О, да! 2-й подход гораздо лучше.

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

                                                                                  Самое читаемое