Код
#статьи

Антон Соснин: «Писать на С++ — это типичный стокгольмский синдром»

Почему вокруг С++ столько мемов, заменит ли его модный Rust и что такое искусственное зрение.

Иллюстрация: fmxexpress / resize / Wikimedia Commons / Next Academy / Unsplash / Дима Руденок для Skillbox Media

Подводные камни С++

— Ты пробовал разные языки, смотрел мемы про «плюсы» — о том, что «сишники» стреляют себе в ногу и всё такое, — и всё равно остался на С++. Почему?

— Как и многие программисты, я писал на разных языках, само собой. Немножко на Python, немножко на JavaScript. Сейчас у меня третье рабочее место, и здесь любят Qt и QML. Но С++ — язык, который я знаю на уровне, достаточном, чтобы мне за это хорошо платили. Конечно, посещают идеи выучить ещё что-нибудь для общего развития. Но как только я хочу начать, появляется много работы и становится не до того.

— Деньги — это хорошо. А есть ли в С++ какие-то минусы?

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

Очень много разных фич, которые пересекаются и синтаксически очень похожи. Например, недавно в чатик «Айти Тудэй» пришли мои бывшие коллеги с вопросом: «А вот если написать int и его не инициализировать, а в следующей строчке написать тот самый int, знак равно и фигурные скобочки — он будет нулём или не будет?» Дима Свиридкин, небезызвестный по Twitter, им ответил: «Нет, лучше так не писать. Напишите просто 0, а в скобках добавьте: „Если int, то будет 0“. Потом другой коллега признался, что любая структура, которая содержит в себе int, — это кошмар, да и фигурные скобочки — это в С++ всегда что-то разное.

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

Вы не знаете С++

— Когда можно с чистой совестью сказать, что ты знаешь С++? Особенно если сравнивать с другими языками: например, питонист стал джуном, поработал годик — и теоретически может рассчитывать на мидловские позиции. В С++ сколько этот путь занимает?

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

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

В С++, по сути, упаковано несколько языков: язык макросов, который ещё с С идёт, ООПшный рантаймовый С++ и язык шаблонов в compile time. Все они тьюринг-полные, на них можно полностью реализовать какую-нибудь логику. Но их ещё нужно между собой подружить, чтобы они правильно компилировались, к тому же на разных платформах. Люди же как привыкли думать: «С++ — кросс-платформенный язык. Давайте его возьмём. Хороший вариант».

Как понять, что человек выучил С++? Могу сказать про себя. Надо походить по собеседованиям, поговорить с другими разработчиками. Если находишь общий язык с людьми, к которым пытаешься устроиться на работу, можешь себя оценить: вот здесь я разбираюсь, а здесь поплыл. Но чтобы утверждать, что ты полностью освоил С++, надо знать подмножество, которым ты пользуешься в своей работе. Я, например, метапрограммированием занимаюсь нечасто и потому всё время гуглю, подглядываю в Cppreference.

Три составные части С++

— Можешь чуть подробнее рассказать про три языка в С++, о которых ты упомянул? Что это за язык шаблонов, что за язык макросов и что за язык ООП? Как человеку понять, в чём различия?

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

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

Сейчас в С++ появляется на этапе компиляции третья часть языка — можно сказать, отдельный язык. Там есть constexpr — выражения, которые уже известны на этапе компиляции и на которых можно производить вычисления. Например, в последних стандартах большинство контейнеров — constexpr. Соответственно, можно на этапе компиляции уже что-то сложить в вектор, применить какие-то алгоритмы, и в рантайме это вычисление происходить не будет.

Прежде чем изучать C++, хорошенько подумайте, надо ли оно вам

— Где сейчас оправданно использовать «плюсы», а для каких задач они уже не подходят?

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

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

Если даже берёшь какой-нибудь сторонний фреймворк (например, в Qt, в некоторых решениях от Intel и других компаний), там встречаются всё те же проблемы. Просто они от тебя скрыты, потому что ты не разработчик, а пользователь. Другие языки, наверное, лучше подходят для подобных задач.

Как и в каком направлении развивается C++

— А как вообще развивался С++? Куда он движется, что будет дальше?

— С++ был уже в девяностых — как наследник С. В нулевых, как считается, возник определённый застой, потому что не было ещё накатанной системы стандартизации. Но при этом активно развивались всевозможные библиотеки: Boost, Qt, OpenCV. Придумали всевозможные конструкции, концепции, которые сейчас являются основополагающими. Например, умные указатели RAII. А уже в 2010-х годах появился 11-й стандарт, где реализовано много того классного, что придумали за нулевые. Он получился мощным, хорошим — это база, которой сейчас пользуются все.

14-й стандарт просто чуть-чуть поправил огрехи 11-го. 17-й опять принёс кучу фич, из которых я помню сейчас только std::filesystem. Сейчас 20-й: с концептами, ренджами, прочими фичами. Это всё усложняет язык, с одной стороны. С другой — в некотором смысле становится проще писать, но нужно вводить для себя ограничения.

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

— Как объяснить человеку со стороны, чем различаются C#, С++ и С? Был С — некая базовая штука, потом его улучшили — сделали С++, а потом Microsoft пришёл и сделал какой-то С с решёткой…

— Это стандартная история. Как английские слова car и carpet («машина» и «ковёр») — что-то общее между ними вроде есть, но концепции совершенно разные.

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

Почему С++ — боль и за что он в игноре у Торвальдса

— Есть ли в С++ то, что можно назвать синтаксическим сахаром, — суперкрутые фичи, которым могут позавидовать другие языки?

— Честно говоря, я не знаю ни одного человека из другого языка программирования, который завидовал бы разработчику на С++. Преференций, кроме стокгольмского синдрома, к сожалению, никаких.

— Ядро Linux делают на С. Почему Торвальдс не пускает туда С++, на твой взгляд? Какие объективные причины?

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

— То есть С в каком-то плане проще, чем «плюсы»?

— Намного проще. Это не значит, что на нём нельзя реализовать те же вещи, что на С++. Другое дело, что он сильно ограничен своими языковыми конструкциями и концепциями.

Например, если некто разработает «железку» на какой-то своей воображаемой архитектуре, он может там сделать собственный С, потому что это довольно просто и не требует большого количества человеко-часов. Это одна из стандартных, мне кажется, лабораторных работ для студентов — реализовать какое-то подмножество С.

Всё об экосистеме С++

— Что входит в экосистему С++? Какие библиотеки, фреймворки, тулинг и так далее?

— Какой болезненный вопрос! У С++ нет экосистемы как таковой. Если мы берём Rust или Go — там есть компилятор, который сразу автоматически всё форматирует, тыкает пальцем в ошибки, а в Rust ещё и ссылку на документацию в ошибках выведет. Всё понятно и хорошо. У Rust сразу идёт менеджер пакетов, и у Go тоже это всё есть под капотом.

У С++ есть компилятор — и всё. Как говорят: «Что вам нужно, чтобы начать писать на С++?» — «А ничего, у вас есть компилятор в операционной системе. Вы можете писать на С++».

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

Впрочем, в Clang, в Visual Studio, по-моему, всё уже очень хорошо. Ещё я пользовался актуальными версиями GCC и могу сказать, что в последние годы компиляторы стали гораздо человечнее.

Из тулинга у нас есть весьма странный CMake. До него был Make, но это как car и carpet — разные вещи. Конечно, у Clang классный тулинг с кучей всяких утилит: ClangFormat, который помогает форматировать код; Clang-Tidy — статический анализатор. Это помогает нам не стрелять в ногу там, где по невнимательности такое можно сотворить.

Если у вас есть возможность разрабатывать на Windows с помощью Visual Studio — устанавливайте её. По моему мнению, это идеальная IDE для разработчика на C++. Если вам надо по работе, то, скорее всего, работодатель её купит, а если для себя — пользуйтесь Community Edition для студентов и преподавателей — она бесплатная. Там есть профайлер даже из коробки. Когда я разрабатывал под Windows, это было просто шикарно.

Ещё есть хороший, зрелый менеджер пакетов Conan. В своём текущем проекте я перевёл всё на Conan буквально за один день, и все с удовольствием пользуются. Не надо мучиться с самостоятельной сборкой каких-то third-party-зависимостей — всё соберётся само.

— А если не под Windows и не Visual Studio, какие ещё IDE можешь порекомендовать?

— Я последние года три пользуюсь VS Code. Это вроде текстовый редактор, но с помощью расширений из него можно сделать хорошую IDE под любой язык. На С++ всё хорошо, всё отлаживается, всё запускается, разрабатывается, форматируется — и прикручивается Clang-Tidy.

Конечно, в полноценной Visual Studio всё чуть более гладко, рюшечками покрыто, спрятано, и есть профайлер. И отладка, конечно, поприкольнее, потому что создатели добавили очень много крутых фич с 2017 года.

Qt Creator — хорошая IDE. Немножко деревянная, на мой взгляд, там прибито гвоздями многое, но в целом неплохо.

Есть любители, конечно, CLion от JetBrains, но у меня как-то не складывается со всем, что на Java написано. Не идёт у меня такое. Кроме SmartGit — это хороший софт.

— Что по библиотекам, по фреймворкам? Какие мастхэв-штуки есть в этом плане?

— Зависит от задачи, которую мы хотим решить. Есть Qt для разработки UI, для кросс-платформенной разработки. C этой библиотекой можно и веб сделать, и ПО для встраиваемых систем писать.

Совместим ли С++ с другими языками

— Как обстоят дела у С++ с интероптом? Он стыкуется с другими языками?

— Как и в остальном — всё очень своеобразно. Где-то между «плохо» и «хорошо».

С++ прозрачно интеропится с С, синтаксически всё очень похоже и легко компилируется. Проделав некоторые движения, можно сразу подключить библиотеку. Потом, раз это С, можно куда-нибудь в NDK в Java подключать и делать обёртки для Python.

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

Если с Clang и GCC дело ещё куда ни шло, то с Visual Studio ни о какой совместимости говорить нельзя. В любом случае мы собираем код для определённой архитектуры, для определённой операционной системы и для определённого компилятора. И когда хоть одна из этих переменных меняется, всё идёт совершенно иначе.

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

— Какие ещё есть компиляторы С++ помимо тех, что ты уже перечислил?

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

Есть Embarcadero от ребят, которые делают Delphi и С++Builder. Это из того, что я помню. Их, конечно, немного больше, но всё-таки самые популярные — это наши любимые бесплатные GCC и Clang. Ну и MSVC — тоже неплохой компилятор, популярный и вполне работающий.

С++ против Rust: кто кого

— Разговора о Rust никак не избежать, если говорим про С++. Есть мнение, что это классная замена С++. Насколько это реально на практике?

— Не могу сказать, где он слаб, где силён, потому что я на Rust не писал, я на нём читал. Если есть язык, который использует более современные концепции, — почему бы его и не взять? Он разработан уже со взглядом на ошибки прошлого, он не тянет за собой огромное легаси. У него много преимуществ.

Единственное ограничение — на Rust ещё не всё переведено, а что переведено — к тому есть вопросы, насколько хорошо. Это не камень в огород, это о том, что не пройдена проверка временем. Но многие ребята сейчас начинают что-то делать на Rust, чтобы внедрить в свои проекты, которые написаны на С++. Поэтому, если что-то проще и надёжнее написать на Rust, пишите на Rust.

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

Бегите, глупцы, или Что почитать, если вы по-прежнему хотите выучить С++

— Что стоит читать по С++, за какими известными людьми из комьюнити следить?

Я читаю Виктора Зверовича, это автор fmtlib. Читаю Николая Джосьютиса, Эрика Ниблера — это автор Ranges в 20-м стандарте. Ещё порекомендовал бы Тимура Думлера, он тоже есть в Twitter. Также у нас есть CppCon на YouTube — там со временем появляется всё и бесплатно. И C++ Russia — там появляется не всё, но недостающее можно найти на YouTube. Попросите работодателя — вам оплатят, если вы хотите получить доступ к записям. Таким образом можно держать, мне кажется, руку на пульсе.

— Если человек хочет вкатиться в программирование через С++ или задумывается о том, чтобы перейти на С++ с другого языка, ты бы какое наставление ему дал? Беги, глупец?

— Да, примерно так.

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

Но если кому-то очень хочется, то я такого человека не остановлю никаким напутствием. Он сам найдёт свой путь.

— А сам ты получаешь удовольствие от С++ и вообще от программирования?

— От С++ — когда как. Если ты для себя определил, что сейчас мы этим маленьким кусочком С++ будем решать задачу, — это интересно. Воевать с языком неинтересно. Когда у тебя ошибка компиляции ведёт куда-нибудь в стандартную библиотеку, проблема точно не в библиотеке — она в коде. Но скажите, пожалуйста, откуда этот стек развернулся? Зачем вы мне его показываете? Покажите место, с которого в моём коде началась эта история!

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

Что такое компьютерное зрение, на чём его пишут и при чём тут C++

— Ты довольно долго работал над компьютерным зрением…

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

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

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

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

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

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

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

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

Но если у вас только TensorFlow и больше ничего в проекте — наверное, это неплохое решение. Наконец, есть OpenVINO от Intel — тоже встречается время от времени.

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

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

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

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

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

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

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

Наверное, есть. Но я в тему входил сам: что-то гуглил, какую-то читал документацию, иногда исходники — OpenCV. Когда у нас был большой интерес к этому — ещё во времена работы с фоторедактором, — один из коллег посоветовал книгу Рафаэля Гонсалеса «Цифровая обработка изображений». Там база хорошая — что такое контраст, как его крутить, что такое яркость, в принципе как устроены изображения, что с ними можно делать, как их можно вытягивать и улучшать.

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


Проверьте свой английский. Бесплатно ➞
Нескучные задания: small talk, поиск выдуманных слов — и не только. Подробный фидбэк от преподавателя + персональный план по повышению уровня.
Пройти тест
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована