СРАВНЕНИЕ ЯЗЫКОВ ПРОГРАММИРОВАНИЯ С++ И С#
В современном мире существует огромное количество языков программирования, из которых применяются около 700, а 20 из них пользуются особой популярностью [1]. Вследствие этого многие начинающие разработчики сталкиваются с проблемой выбора определенного языка для изучения. Ее решение требует углубленного понимания особенностей рассматриваемых языков программирования, их слабых и сильных стороны, областей их применения. 
В данной статье приведен анализ и сравнение C++ и C#, входящих в топ-5 рейтинга GitHub PYPL [2], отражающего наиболее популярные языки программирования по поиску учебных материалов. Они располагаются на 4 и 5 местах соответственно, оба являются C-подобными и на первый взгляд кажутся очень похожими. Однако это и представляет интерес для их сравнения. Кроме того, существует ряд работ по данной проблематике, но информация, приведенная в них, очень поверхностная. Один из ярких примеров – статья Ерлыковой М.С., Зайковой Е.А. «Comparison of C++ and C# programming languages», опубликованная в журнале «Молодежь. Общество. Современная наука, техника и инновации» 2018 года (№ 17. P. 29-30. URL: https://elibrary.ru/download/ elibrary_ 35440878_34322030.pdf (дата обращения: 20.04.2023)).  
Для того, чтобы описать предметную область исследования и указать основные эволюционные вехи ее развития, рассмотрим историю развития C++ и C#. Язык программирования C++ разработал Бьёрн Страуструп в 1980 году, будучи сотрудником AT&T (American Telephone & Telegraph) Bell Laboratories. Изначально C++ был известен под названием "C с классами" и подразумевался как совокупность усовершенствований для C с целью более простого и приятного написания кода. В нем сохранена совместимость с кодом C и предоставлены его некоторые важные характеристики. На данный момент, никто не обладает правами на C++, так что он развивается во всех возможных направлениях для большего удобства пользователей. Язык программирования C# был разработан компанией Microsoft в конце 1990-х - начале 2000-х годов группой разработчиков под руководством Скотта Вильтаумота и Андерса Хейлсберга – создателя Turbo Pascal и Delphi. C# стал инструментом для работы с новыми компонентными технологиями Microsoft для обмена сообщениями и данными, а также Internet-приложениями COM+, ASP+, ADO+, SOAP, Biztalk Framework. Сейчас C# позволяет разработчикам создавать разные типы безопасных и надежных приложений, выполняющихся в .NET. Он имеет множество инструментов и библиотек, которые делают его очень гибким и мощным языком программирования для быстрого и эффективного создания высококачественного программного обеспечения. C++ и C# – C-подобные языки, активно развивающиеся в современном мире, однако между ними есть существенная разница. 
Дальнейшее сравнение C++ и C# будет проведено по следующим критериям: область применения, парадигма программирования, компиляция, уровень языка программирования, кроссплатформенность, множественное наследование, типизация, синтаксис, производительность, безопасность использования. 
Область применения. C++ широко используется для разработки программного обеспечения, включая операционные системы, драйверы устройств, приложения для встраиваемых систем, высокопроизводительные серверы и компьютерные игры. Некоторые известные примеры использования C++: игровые движки Unreal Engine и Unity, GPU-вычисления для криптовалют и глубокого обучения, облачные системы хранения и базы данных. C# используется для разработки вебприложений с помощью ASP.NET, мобильных приложений на Xamarin, видеоигр на Unity, программ для защиты систем, консольных приложений.  
Парадигма программирования. В программировании важен подход к написанию программы, то есть совокупность идей и правил, описывающих стиль кода.  
C# – это объектно-ориентированный язык программирования, поддерживающий четыре основных принципа ООП: абстракцию, инкапсуляцию, наследование, полиморфизм. С++ – мультипарадигмальный язык программирования, предлагающий не только объектноориентированное программирование, но и процедурное программирование, обобщённое программирование, функциональное программирование.  
Компиляция. C++ компилируется сразу в машинный код. Компиляторы .NET транслируют код, написанный на C#, на язык CIL (Common Intermediate Language), который можно рассматривать как "ассемблер" виртуальной машины .NET. JIT-компилятор (Just in time), являющийся частью CLR (Common Language Runtime) – общей среды выполнения программ, написанных на языках .NET, преобразует CIL в машинный код.  
Наряду с этим компилятор C++ не выполняет проверку границ массива. При обращении к недопустимому индексу результат выполнения программы будет неверным, но ошибки компиляции, как в C#, не произойдет, что чревато повреждением системы при ошибочном синтаксисе. 
Уровень языка программирования. C++ сочетает в себе свойства как высокоуровневых, так и низкоуровневых языков. Он позволяет работать напрямую с ресурсами компьютера, а также подразумевает ручное управление памятью: если программист создает объект, он несет ответственность за его уничтожение после завершения задачи объекта.  
C# считается высокоуровневым языком программирования. Управляемые объекты размещаются в управляемой куче (managed heap), откуда они автоматически удаляются сборщиком мусора: разработчик не должен самостоятельно задумываться об освобождении места, когда задача объекта будет завершена. Однако C# предоставляет и возможность написания неуправляемого кода, напрямую подконтрольного создавшим его программистам: все операции с данными и алгоритмы должны четко определяться. Таким образом, компания Microsoft спроектировала среду CLR так, чтобы приложения могли состоять как из управляемых, так и из неуправляемых компонентов кода. 
Кроссплатформенность. C++ – это кроссплатформенный язык программирования, он может использоваться на Linux, Windows, MacOS, iOS, Tizen и многих других платформах. На данный момент, используя различные технологии .NET, на языке C# также можно разрабатывать приложения под Linux, Windows, MacOS, iOS, Android.  
Множественное наследование. C++ позволяет реализовывать множественное наследование, когда подкласс имеет два или более родительских класса. Использование множественного наследования требует тщательного проектирования, так как может вызвать неоднозначность. Например, проблема ромба возникает, когда классы B и C наследуют A, а класс D наследует B и C (рис. 1). Если классы A, B и C определяют метод и он будет вызываться классом D, то неясно, какой метод должен быть вызван – метод класса A, B или C. Решение этой проблемы в C++ оставлено на усмотрение разработчика. В C# множественное наследование не поддерживается. 
Рисунок 1 – Ромбовидное наследование 
Типизация. Хотя C#, как и C++, считается статически типизированным языком программирования, в его последних версиях появились некоторые динамические возможности. В .NET 4.0 была добавлена среда DLR (Dynamic Language Runtime), позволяющая создавать динамические объекты, члены которых выявляются на этапе выполнения программы, и использовать их вместе с объектами со статической типизацией. 
Синтаксис. Синтаксис C# проще, чем у C++ (рис. 2). Кроме того, одним из удобств С# является автоматическая подсказка дальнейшего кода из существующего контекста. Это может помочь опытному программисту писать программу быстрее, а начинающему – подсказать возможные варианты кода. Также среда предлагает использовать последние синтаксические нововведения и собственные решения найденных ошибок. 
Рисунок 2 – Примеры синтаксиса C# и C++ 
Производительность. Под производительностью обычно понимают скорость выполнения программ. Это один из самых главных критериев при сравнении языков программирования. Так как существует большое разнообразие задач и вариантов их реализаций, при оценке скорости могут возникнуть неоднозначности и противоречия. Именно поэтому производительность – это один из самых сложных критериев. 
В C# вычислительные циклы, потраченные на код JIT-компилятора, выделение и освобождение памяти сборщика мусора, требуют дополнительных ресурсов и времени, в отличие от кода на C++, который компилируется непосредственно в машинный код. При этом современный JIT-компилятор оптимизирует код под конкретную платформу, а сборщик мусора предоставляет высокоскоростную службу распределения с хорошим использованием памяти и отсутствием долгосрочных проблем фрагментации, что невозможно автоматизировать на C++.   
Кроме того, важно учитывать, что скорость выполнения программы напрямую зависит от квалификации разработчика и качества оптимизации кода, а производительность, оценивающаяся на микроуровне, не определяет производительность на макроуровне и наоборот. Существует слишком много различных факторов, влияющих на конечный результат: сама задача, проблемная область, реализация решения, оборудование и многие другие. В каждой конкретной ситуации необходимо тестировать код на обоих языках для понимания, какой из них может быть наиболее подходящим для достижения поставленной цели. 
Однако сейчас мы можем оценить относительную производительность C++ и C#. Для этого на обоих языках программирования реализуем создание массива и листа на 10000 элементов, их заполнение и сортировку (для массива будет использоваться пузырьковая сортировка, для листа – встроенная функция сортировки) и измерим затраченное время в тиках. Для разработки программы, которая легла в основу сравнения производительности, был выбран продукт корпорации Microsoft – Visual Studio 2022. Платформа для написания кода на C# – .NET 7.0. Полученные данные представлены на 3 рисунке: в итоговых строках таблиц для удобства восприятия тики переведены в приближенное значение в миллисекундах. 
Рисунок 3 – Скорость работы с массивом и листом на C++ и C# 
В результате проведенного исследования и полученных данных можно сделать вывод, что работа с массивом происходит быстрее на языке C++, но затраченное время на создание листа, его заполнение и сортировку суммарно меньше у C#.  
Безопасность использования. В ноябре 2022 года Агентство национальной безопасности (АНБ) США выпустило отчёт, в котором указало на то, что широко используемые языки программирования C и C++ дают хакерам больше возможностей для использования эксплойтов – вредоносных программ, эксплуатирующих уязвимости системы. В связи с этим АНБ советует организациям рассмотреть возможность перехода на языки программирования, обеспечивающие защиту памяти, такие как C#, Go, Java, Ruby, Rust и Swift. По мнению экспертов, это поможет предотвратить возникновение определённых типов уязвимостей, связанных с памятью.  
Автор языка программирования C++ Бьёрн Страуструп дал официальный ответ на рекомендации АНБ. По его мнению, упомянутые «безопасные» языки программирования на самом деле не превосходят C++ в важных с его точки зрения применениях. В частности, развиваемые в последние годы базовые рекомендации по использованию C++ (C++ Core Guidelines) охватывают методы безопасного программирования и предписывают разработчикам применение средств, гарантирующих безопасную работу с типами и ресурсами. Например, анализатор Microsoft Visual Studio и его профиль безопасности памяти обеспечивают большую часть поддержки CG сегодня, и любой хороший статический анализатор (например, Clang tidy, который имеет некоторую поддержку 
CG).  
Обобщим выводы по итогам проведения сравнительного анализа. C++ и C# – C-подобные статически типизированные языки программирования общего назначения, поддерживающие объектно-ориентированное программирование и низкоуровневые операции. Также на них можно писать кроссплатформенные приложения, системные приложения, игры. Из этого логично предположить, что C++ и C# действительно очень похожи, но это и усложняет понимание важных различий между ними. В проведенном исследовании были выделены следующие специфики рассматриваемых языков программирования: 
1. C++ не ограничивается ООП и предлагает процедурное, обобщённое, функциональное программирование. C# же разрабатывался как объектно-ориентированный язык. 
2. C++ изначально предполагает прямую работу с ресурсами компьютера, поэтому особенно эффективен при прямой работе с ресурсами компьютера. Основой программ C# является безопасный режим, однако программа может частично состоять из неуправляемого кода или использовать его.  
3. JIT-компилятор C# имеет намного больше возможностей относительно C++ для оптимизации даже при условии затрат на вычислительные циклы. 
4. C# устраняет возможные неоднозначности, не поддерживая множественное наследование и реализуя проверку кода на этапе компиляции, что не предлагает C++. 
5. Хотя C# считается статически типизированным языком программирования, в нем добавлены варианты использования динамической типизации. 
6. Синтаксис C# проще для изучения новичку, чем синтаксис C++. 
7. Сравнение производительности C++ и C#, приведенное в данной статье, не показало однозначного превосходства одного из языков программирования. Тем не менее стоит учитывать, что результаты, показанные на конкретном примере реализации работы с массивами и листами, не характеризуют их использование, например, в крупных проектах.  
8. Вопрос безопасности использования языка C++ вызывает множество противоречивых мнений.  
Таким образом, C++ является более быстрым и легковесным языком для задач, требующих много низкоуровневых операций, таких как управление памятью или системное программирование. При этом его некорректное использование может привести к возникновению уязвимостей системы. C# имеет больше накладных расходов из-за компиляции для среды выполнения .NET, которая добавляет слой между кодом и аппаратным обеспечением. Однако C# имеет преимущество в скорости выделения памяти и оптимизации в целом. Кроме того, C# имеет более простой и современный синтаксис, чем C++, что может повысить производительность разработки, особенно в условиях минимального срока для реализации программы. В конечном итоге выбор языка зависит от задач и предпочтений разработчика. При имеющихся возможностях в конкретных проектах код можно тестировать на обоих языках программирования для понимания, какой из них наиболее подходит для достижения поставленной цели. 
Современные возможности настолько безграничны, что освоить практически любой навык можно с изумительной легкостью и в достаточно короткие сроки. Если сравнивать в данном контексте C# и C++, изучение первого займет меньше времени, что делает его доступным вариантом для начинающих разработчиков. C++ требует от пользователя глубокого понимания фундаментальных вещей: архитектуры компьютера и операционных систем, сетевых технологий и многого другого. 
Именно поэтому, после C++ изучение других языков становится намного проще и быстрее.  