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

Я долго не мог выразить вербально, что меня так отталкивает в C++. Однажды из любопытства меня заинтересовал Rust. Я влюбился в него не сразу, сделав не менее 3х подходов к снаряду изучению, пока наконец-то не нащупал интуитивное понимание. С этого момента Rust превратился для меня в эталон инструмента для системного программирования.

Так что и где не так?

Отношение к Rust делит людей на два полярных лагеря: одни его любят за его явные преимущества, другие - беспричинно ненавидят.

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

Я также пытался проанализировать свою неприязнь к C++. Заодно пытался поставить себя на место хейтеров Rust и понять их мотивацию. Это долго не получалось, но вдруг...

Картинка сложилась

Для меня C++ является языком, требующим колоссального внимания в силу неимоверного количества правил, исключений и просто абсолютно нелепых конструкций с точки зрения языкостроения.

Я сейчас даже не говорю о тяжелом наследии C, достаточно одной такой вещи современного C++: стандартизационный комитет придумал семантику перемещения и ввел в язык, помимо физического use-after-free, еще и логический use-after-free, возникающий в результате доступа к объекту, из которого выполнено перемещение. Думаю, понятно, что подобного и близко нет в Rust.

Почему воротнички

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

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

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

Заключение

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

Поэтому когда вам в очередной раз доведется слышать стандартный спор C++ vs Rust, вспомните эту заметку и определите для себя: вы либо синий воротничок, либо — белый. И когда напротив вас появляется человек другой окраски воротничка — перестаньте напрягаться. Диалога все равно, скорее всего, не выйдет.

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


  1. pavlushk0
    16.12.2025 05:13

    "...логический use-after-free..." - простое правило, не обращайся к объекту в moved-from стейте (даже если очень хочется, и есть сто кейсов когда нужно и т.д и т.п.). Можно не использовать move вообще. Вообще можно не использовать вещи которые не нужны, а маргинального говна в c++ полно, хоть тоже виртуальное наследование.

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


    1. Kelbon
      16.12.2025 05:13

      То что автор назвал логическим use after free это буквально относится к любому обращению к переменной после её изменения. Например после swap или просто вы сделали clear на векторе и потом обратились к нему.

      В общем претензия самая нелепая из всех что представители языка ада2 предъявляли С++


  1. 8street
    16.12.2025 05:13

    Для меня C++ является языком, требующим колоссального внимания в силу неимоверного количества правил, исключений и просто абсолютно нелепых конструкций с точки зрения языкостроения.

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


    1. apevzner
      16.12.2025 05:13

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

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

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


      1. eao197
        16.12.2025 05:13

        В реальности чаще получается ограничивать себя

        Оно бы звучало весомо... Только вот это говорит человек, который пишет на чистом Си и go, а не на C++ (и даже толком не знает C++, что уже неоднократно было продемонстрировано на RSDN).

        В C++ гораздо чаще приходится ограничивать себя тем, что есть в компиляторах.


        1. apevzner
          16.12.2025 05:13

          В C++ гораздо чаще приходится ограничивать себя тем, что есть в компиляторах.

          Я примерно про это и говорю. Угу, тем, что есть в компиляторах...


          1. eao197
            16.12.2025 05:13

            Только вот это принципиально отличается от высказанного выше:

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

            Здесь тов. @8street наверняка говорил о фичах языка, которые выбираются (или отвергаются) безоностительно возможностей компилятора. И у которых, по хорошему, должна быть мотивация из категории "потому что". Например, запрет на использование исключений потому что real-time или низкоуровневый код драйвера. Или запрет на использование RTTI потому что в итоговом исполняемом файле остается слишком много информации об исходном коде. Или запрет на использование unified initialization syntax потому что запись v{x, y} будет вести себя неожиданным образом, если v -- это std::vector или std::string.

            Как правило, такие рекомендации формируют подмножество языка, работа с которым не должна вызывать проблем (как у команды разработки, так и при эксплуатации).


  1. AlexGorky
    16.12.2025 05:13

    "Не путайте туризм с иммиграцией".
    Возможно, если начнёте писать на Rust за деньги, и его тоже возненавидите ))

    Сходу вот нашёл чью-то боль и вот и вот.
    Претензии - медленная компиляция, сложный для понимания синтаксис (например "Pin<Pin<&dyn LocalTrait>>") и т.п.

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


  1. MinimumLaw
    16.12.2025 05:13

    Отношение к Rust делит людей на два полярных лагеря: одни его любят за его явные преимущества, другие - беспричинно ненавидят.

    Ох не люблю я эти темы... Вы говорите "К тому же я занимаюсь системным программированием, а это налагает дополнительные требования к знанию языка."

    Проблема ровно в том, что у меня с вами очень разное понимание "системного программирования". В моем мире этим термином называют тот код, который НЕПОСРЕДСТВЕННО работает с аппаратурой (все эти DMA каналы, контроллеры прерываний, таймера, системные таблицы, регистры периферии и самого процессора). Этот код - фундамент. Соответственно, любой язык, который прячет от меня этот код для меня неприемлем. В частности C++. Для меня не очевидно как именно код на плюсах будет преобразован в ассемблер, и как итоговый код будет меняться в зависимости от ключей оптимизации или используемого компилятора. Лучший вариант - ассемблер. Самый разумный компромисс - С (без всяких плюсов). Все, что описываете вы работает на уровне выше. Для меня это частный случай прикладного ПО. И да, я не очень понимаю как делить его на уровни.

    А еще, чисто для аналогии, есть вполне традиционный подход в современном загородном строительстве. Перезаклад на фундамент. Его делают заведомо сильно более мощным, чем требуется. Rust - эти аналог такого подхода, перенесенный в мир вычислительной техники. В подавляющем большинстве случаев это работает. Хоть и стоит значительно дороже. И в этом смысле нет проблем - пусть будет Rust. Но как в строительстве остается спрос на фундаменты без перезаклада, так и здесь разного уровня ассемблеры, скорее всего, никуда не денутся. Не всех устроит тот самый перезаклад. Более того, в строительстве уже активно отходят от такого подхода. Ибо у него уже находятся объективные изъяны. Например повышенная усадка или разломы из-за увеличившейся массы, или повышенные требования к качеству материалов. И это не считая главного - цены вопроса. Лично у меня нет сомнений в том, что рано или поздно и с Rust будет ровно то же. Это довольно молодой язык. Но молодость проходит. Наивно полагать, что Rust останется "вечно молодым". С доказал, что умеет взрослеть и красиво стареть. Впрочем, помирать он пока не собирается. Более того - пока молодые у него учатся. И это хорошо.


    1. apevzner
      16.12.2025 05:13

      Проблема ровно в том, что у меня с вами очень разное понимание "системного программирования". В моем мире этим термином называют тот код, который НЕПОСРЕДСТВЕННО работает с аппаратурой

      Я тоже работаю с аппаратурой, но только в последние несколько лет моя аппаратура - это принтеры и сканеры. Это такие довольно сложные железки, которые разговаривают с хостом в основном по сети или по USB.

      Желание иметь 100% видимость и контроль на стыке железа и софта очень понятно. Непонятно, зачем для этого ассемблер. В целом, компилятору можно доверять, обычно всё же он нагенерирует то, что написано (в рамках свобод, гарантированных ему спецификацией языка). Мешают библиотечные автоматизмы, которые могут влиять на семантику действий.

      В этом плане Go, например - вполне годный язык. Потому что от него можно добиться того, чтобы памятью он управлял, а в протокольные дела не лез, оставив видимость и контроль, сравнимые с ANSI C. Да, времянку он не всегда гарантирует, но мои устройства не настолько чувствительны к времянке.


      1. MinimumLaw
        16.12.2025 05:13

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


        1. apevzner
          16.12.2025 05:13

          Для принтеров и сканеров, драйвера которых по сути фильтры - это допустимо

          В некотором идеальном мире драйвера принтеров (но не сканеров) - это фильтры, которые преобразуют условный PostScript в условный URF или PWG-Raster.

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

          Я писал драйвера сетевых карт, в т.ч, и Wi-Fi, с достаточно сложной логикой на хосте. Мне эта тема вполне знакома.

          Переключатель задач на С я тоже, кстати, писал :)


          1. MinimumLaw
            16.12.2025 05:13

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


            1. apevzner
              16.12.2025 05:13

              Сколько драйверов надо написать, чтобы из автолюбителя превратиться в автомеханика? :)


              1. MinimumLaw
                16.12.2025 05:13

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


                1. apevzner
                  16.12.2025 05:13

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

                  Желание слазить на уровень ассемблера пару раз присутствовало и ни разу в итоге не оправдывалось.

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


  1. eao197
    16.12.2025 05:13

    Основной посыл статьи от меня ускользает. Кажется, что ключевое -- это:

    Диалога все равно, скорее всего, не выйдет.

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