Почему язык С++ такой недружелюбный к программистам

Привет, меня зовут Максим. Я программист-самоучка, свою первую строчку кода написал еще в 1994 году и на текущий момент принял участие где-то в 10 игровых проектах.

За это время мне пришлось писать на множестве различных языков:

  • с 8 по 11 класс самостоятельно изучал BASIC и Turbo Pascal в компьютерном классе школы;
  • писал игры для калькулятора МК-61 дома (в средине 90-х компьютер был роскошью);
  • Delphi на первой работе;
  • Lua и немного C++/CLI на второй, с которой я вошел в GameDev 14 лет назад;
  • Python и C++ под Bigworld на третьей;
  • C# под Unity на текущей;
  • в свободное время делаю свои проекты;
  • та же некоторое время посвятил изучению Rust и D в попытке найти альтернативу C++.

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

В очередной раз с C++ работал пару месяцев назад, когда взялся разбираться с Unreal Engine. И поразился, сколько еще неизведанного осталось для меня в этом языке. Сколько еще подводных камней и возможностей выстрелить себе в ногу я подзабыл или не нашел при прошлых опытах использования.

Эта статья — попытка осмыслить, почему у C++ такой высокий порог вхождения, чем он уступает другим языкам. А также почему я считаю его плохим языком для программистов-новичков.

Целевая аудитория:

  • те, кто считает, что начинать нужно со сложного и максимально эффективного;
  • те, кто много писал на C#|Java и подобных и хочет покорить новые вершины;
  • те, кто имеет некоторый опыт C++, но, как и я, понимает, что нет предела совершенству;
  • практикующие системные программисты на языках типа Rust и D, которые смогут рассказать, почему выбрали их альтернативой C++;
  • гуру C++, которые в комментариях просветят неопытных, чем и на сколько оправданы те или иные подходы языка, затронутые в статье.

Иллюстрация Ульяны Патоки

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

Компиляция и линковка

Первое, с чем приходится столкнуться, — архаичное правило, что «единицей компиляции является файл», которое перекочевало в С++ из языка С. Это означает, что если файл ссылается на что-то из других файлов, то нужно каким-то образом сообщить компилятору тот минимум информации, что позволит ему выполнить работу. Такой информацией являются преимущественно объявления используемых этим файлом функций — копии заголовка функций без тела.

Чтобы компилятор получил эту информацию, сначала отрабатывает препроцессор. Он не менее архаичным способом переносит все содержимое каждого включаемого файла в тот, который компилируется. Если в каком-то из этих файлов были включения, они тоже добавляются.

Чтобы не включать избыточую для компилятора информацию (ему код включаемых функций не нужен), договорились все заголовки функций выносить в отдельные файлы, которые и назвали заголовочными. Таким образом возникло разделение, что заголовочные файлы имеют расширение .h (иногда пишут .hpp, чтобы явно указать, что это написано на С++), а файлы с кодом — в файлах с расширением .cpp.

Правда, копирование даже заголовков в другие файлы при каждой их компиляции в большом проекте приводит к тому, что подготовка файлов к компиляции и сам процесс компиляции занимают достаточно много времени. Активное использование шаблонных классов, которые при специализации создают как бы полную копию класса для каждого типа, еще больше усугубляет ситуация с временем компиляции. В результате без специальных ухищрений типа Precompiled Headers, IncrediBuild время компиляции будет на порядок дольше схожих по размеру проектов на других языках. Но даже с ними время компиляции будет значительно уступать.

Приведу пример.

Сейчас я работаю над проектом на C# под Unity, который состоит из 4300 файлов с кодом. Это 25 мегабайт исходников! Время полной компиляции проекта на моем компьютере занимает 10 секунд. Берем пустой проект на Unreal, добавляем единственный объект с С++ классом. Вносим туда малейшее изменение — время компиляций и линковки до запуска, минимум 7 секунд на том же i7-8700.

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

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

Для компилятора это может быть проблемой, и для ее решения сейчас используют директиву препроцессора #pragma once. Выглядит это так:

// unit.h
#pragma once
 
void f1(); // пример описания заголовка (сигнатуры) функции f1()
bool f2(int x); //пример описания заголовка (сигнатуры) функции f2()

Но вы можете увидеть и такой вариант решения проблемы, которым пользовались до появления поддержки #pragma once:

// unit.h
#ifndef __UNIT_H__
#define __UNIT_H__
 
void f1(); // пример описания заголовка (сигнатуры) функции f1()
bool f2(int x); //пример описания заголовка (сигнатуры) функции f2()
 
#endif

Здесь для каждого файла программист придумывал уникальное имя константы препроцессора. Тогда код между #define и #endif включался только при первой попытке подключить этот заголовочный файл к текущему компилируемому файлу.

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

Похожие статьи:
Цього разу ми зустрілися з глядачами у Києві й разом записали 40-й випуск подкасту. На захід прийшло майже 70 людей. Разом ми не тільки...
Новые версии ReactOS 0.4.0 Kotlin 1.0 Vulkan 1.0 Docker 1.10 Go 1.6 TypeScript 1.8 htop 2.0 ESLint v2.0.0 FFmpeg 3.0 GitLab 8.5 Аналитика Ukraine has an army of nearly 100,000 IT professionals working for 100+ global...
У свіжому випуску новинного дайджесту DOU News обговорюємо рівень зарплат українських розробників, нові лейофи, перемогу українців...
За окном карантин, и многие сейчас пытаются придумать решение для помощи в борьбе с COVID-19. Мы в VITEch Lab Healthcare также работаем...
Всех с наступившими праздниками! Меня зовут Виктор, и я работаю менеджером проектов в компании Cogniance. Делюсь дюжиной...
Яндекс.Метрика