Спробую підняти спірну, але, думаю, цікаву тему. Для початку представлюся. За родом діяльності я спеціалізуюся на розробці десктопних додатків під Windows, тому здебільшого з цієї позиції і буду виконувати порівняння.
На старті проекту часто може виникнути питання про вибір засобів розробки і якщо в одних випадках відповідь на це питання випливає з потреби сумісності з бібліотеками і додатками, то в інших відповідь не очевидна.
Окремих статей потребує розгляду вибору Java або інтерпретованих мов. Вони будуть кращими, ніж C++ або C # в деяких випадках, однак винесемо такі випадки за рамки даної статті і сфокусуємося на порівнянні З++ і С #.
Для ясності позначу, що під C++ буду розуміти unmanaged код, а під C # - managed код. У статті можна було порівняти managed і unmanaged, але це було б менш корисно практичний. А mixed код, хоча він і становить деякий інтерес, залишимо здебільшого за рамками даної статті.
Прошу вибачити за деяку категоричність висловлювань, однак, думаю, вона потрібна для більш точного донесення думок. Порівнювати буду за критеріями, даючи по кожному деякий висновок заснований на особистій практиці, фундаментальних основах і відомому досвіду використання. Отже, почнемо.
1. Швидкість розробки
З # дозволяє стартувати розробку швидше, а це дозволяє швидше отримати прототип рішення. Швидкість розробки на C # на початкових етапах проекту значно вища порівняно з С++.
Однак, коли інфраструктура проекту створена, основні підходи і бібліотеки обрані, а білд налаштований, швидкість розробки на С++ і швидкість розробки на С # стають приблизно однаковими.
Таким чином, в коротких малобюджетних проектах С # буде мати перевагу по швидкості розробки, але в довгих і відносно дорогих дана перевага буде незначною.
2. Кросплатформеність
З++ кросплатформенний за фактом, хоча і з деякими застереженнями, додатковими витратами, а також бінарною несумісність між платформами.
C #, по факту, виявився не кросплатформенний, незважаючи на існування неофіційних .net оточень під різними платформами і навіть потенційну бінарну сумісність між платформами.
C # спроектовано бути кросплатформенним, однак його розвиток не пішов у цьому напрямку. Тому під Windows утворилася досить повна .net інфраструктура; на інших же платформах рівноцінної інфраструктури не з'явилося.
При цьому для розробки на С++ склалася практично рівноцінна інфраструктура на більшості існуючих платформ, є маса бібліотек, які скомпільовані або можуть бути скомпільовані під будь-які існуючі платформи. Саме тому існує величезна кількість кросплатформенних програм і бібліотек різного масштабу, написаних на С++, на ряду з кросплатформенними бібліотеками є і бібліотеки специфічні для окремих платформ. Все це дає практичний рівноцінні шанси для розвитку додатків на різних платформах.
І хоча С # можливо використовувати для побудови додатків під не-Windows платформи, проблеми, що викликаються використанням .net в не-Windows оточенні, зводять нанівець багато переваг вибору C #. Тому рекомендувати його для кроссплатформного використання можна хіба що якщо код на C # вже написаний. При цьому треба чітко розуміти, що в перспективі це буде приносити додаткові витрати на підтримку.
3. Продуктивність коду та вимогливість до ресурсів
Очевидним є факт того, що можливості з оптимізації unmanaged коду куди ширші, ніж можливості з оптимізації managed коду. Таким чином, пікова продуктивність коду досяжна тільки в unmanaged виконанні, тобто в межі, майже будь-яка задача на С++ може бути вирішена з меншими вимогами до ресурсів. Тому у важких завданнях, пов'язаних з обробкою великої кількості даних, С++ має сильні переваги перед С #.
Але варто розуміти, що при виборі неправильного підходу, на С++ цілком можна написати код, який буде працювати повільніше коду на C #, що виконує тугіше завдання.
Якщо говорити про сукупність суб'єктивних «простоти розробки», «краси коду» і об'єктивної продуктивності, то використовуючи C # простіше написати код, що задовольняє цим критеріям одночасно. Однак це не означає, що продуктивний код на С++ обов'язково буде страшним або складним для сприйняття, просто при його написанні потрібно більш «творчий» підхід для задоволення перерахованих критеріїв одночасно.
Фундаментальні основи переваг С++ в можливості писати код, який буде виконуватися безпосередньо процесором, і можливості прямої роботи з пам'яттю. Звичайно, свобода дає більше можливостей створити собі проблеми, але в ряді випадків це краще, ніж неможливість подолання стелі продуктивності. І ця стеля цілком може призвести, наприклад, до того, що під вирішення завдання, для якого б вистачило одного хорошого сервера, вам доведеться збирати ферму з декількох серверів, або ж до того, що ваш додаток буде вимагати «топового» заліза на завдання, для яких вистачило б заліза випущеного років 7-10 тому.
4. Бібліотеки
Відмінність асортименту C++ і С # бібліотек в тому, що С++ бібліотек більше, вони мають велику історію, за яку стали непогано налагоджені і оптимізовані, часто кросплатформенні, багато з відкритим кодом. Однак при всіх позитивних сторонах С++ бібліотеки як мають дуже різну, часто навіть архаїчну архітектуру, часто не об'єктний, а структурно-процедурний інтерфейс. Пов'язано це з тим, що багато З++ бібліотеки це З бібліотеки.
Інша неприємна особливість C++ бібліотек - це створення і перевизначення своїх базових типів. Багато З++ бібліотеки заводять свої типи рядків, контейнерів, перевизначають деякі базові типи. Цьому є логічні пояснення (краща продуктивність, підтримка кросплатформенності, відсутність відповідних типів на момент написання бібліотеки), проте все це не додає зручності використання і краси коду. Базові ж С++ бібліотеки дають не так багато, як дають стандартні бібліотеки С #, тому підбір правильних бібліотек для проекту С++ - це завдання, необхідне навіть у порівняно простих проектах.
Однак не все так страшно, для С++ є чимало і «красивих» бібліотек. Та й базові бібліотеки постійно розширюються. Питання часто лише в тому, яких жертв потребує ця краса.
У # З перелічених вище проблем значно менше. Величезна кількість бібліотек з .net йде в базі, плюс до них безліч вільно доступних бібліотек, це покриває практично всі першорядні завдання розробки під Windows. Наявність великої кількості стандартних типів майже позбавляє бібліотек, де базові типи перевизначені. І в силу того, що бібліотеки С # порівняно молоді, - інтерфейси бібліотек, як правило, краще вписуються в ті чи інші шаблони проектування, що часто спрощує їх вивчення.
Однак же при найближчому розгляді великий шанс, що під вашу специфічну задачу С # бібліотеки не виявиться, більш того, може виявитися, що і вирішувати таку задачу на С # досить не ефективно, тому подібної бібліотеки не з'явиться і в майбутньому, а якщо і з'явиться, то буде працювати недостатньо швидко.
Друга неприємна особливість бібліотек С # в тому, що багато з них є просто обгорткою над unmanaged бібліотеками, що буде завжди призводити до втрат продуктивності на конверсіях типів, і створювати додаткові проблеми налагодження і поширення.
5. Зручність зневадження
Можна було б просто сказати, що під Window, С # помітно зручніше налагоджувати і на цьому зупинитися.
Однак якщо з якоїсь причини у вас на ряду з mananged кодом з C # збірки використовується unmanaged, то його налагодження буде стане більш складна в порівнянні зі звичайною зневадкою unmamanged коду з С++.
6. Мова і Синтаксис
З першого погляду код С++ і С # дуже схожий зовні. Але різноманіття коду на C++ більше, адже C++ є одночасно і С і С++ і С++ 0х і все це ви можете використовувати одночасно (звичайно, якщо це підтримує ваш компілятор).
З # же, це тільки C #, хоча його синтаксис постійно розширюється. Код на C #, як правило, виглядає простіше і лаконічніше, ніж код С++ (хоча це не завжди можна було сказати про перші версії С #). Мовні конструкції С++ і С # дуже схожі, однак суттєві відмінності можна знайти в деталях.
Якщо C++ можна дорікнути за відсутність «в базі» reflection, пізнього зв'язування і складання сміття. То С # треба дорікнути за відсутність повноцінних деструкторів, відсутність повноцінних макросів, досить грубе налаштування спадкування, відсутність костянтних методів і членів, відсутність глобальним методів (процедур), дуже обмежену підтримку шаблонів, список можна продовжувати... Однак жити без всього цього цілком можна як у випадку C++, так і у випадку C #.
Синтаксис C #, мабуть, можна назвати спрощеною версією С++, таким чином С #, як і будь-яке спрощення, одночасно несе і позитивний і негативний ефекти.
Варто сказати, що більш складний код часто легше пишеться і аналізується, якщо написаний більш простою мовою. З цієї позиції, використовуючи C #, менше шансів допустити помилку в принципово складному коді і більше шансів написати чистий код, володіючи тими ж ресурсами. Це може бути корисно при вирішенні досить складних, але не вимогливих до продуктивності завдань. Однак при цьому більша кількість «синтетики» в С # робить менше оцінку продуктивності коду за його «зовнішнім виглядом».
7. Вартість підтримки
У підтримці програм великої різниці між С++ і С # немає. Хоча варто розуміти, що деякі баги в додатках, написаних на C #, засобами .net виправити неможливо і при необхідності їх виправити вартість підтримки може істотно зрости. Однак якщо говорити про рефакторинг, то часто додатки, написані на C #, рефакторити дещо дешевше.
8. Ризики
Мабуть, основний ризик використання C # - це сильна зав'язка на Microsoft. Звичайно, навряд чи Microsoft кудись зникне в найближчому майбутньому, але варто розуміти, що Microsoft - це комерційна організація, метою якої є вилучення прибутку, а для прибутку потрібні продажі своєї продукції. Тому в інтересах Microsoft розгортати розробку C # і .net так, щоб це призводило до продажів нової продукції Microsoft. Так що якщо інтереси вашої розробки будуть не відповідати інтересам Microsoft, рано чи пізно це може призвести до проблем.
Ризики використання C++ теж є, але це інші ризики. Основним я б назвав проблеми, пов'язані з бінарною сумісністю бібліотек. Якщо ваші бібліотеки не у вихідних, вам важливо, щоб вони були сумісні. Наприклад, перехід на інший runtime буде можливий тільки при перебудові або отриманні нових версій бібліотек, робота ж декількох runtime-ів в одному процесі може призводити до проблем взаємодії. Все це може істотно здорожити розвиток проекту.
Поряд з ризиками розвитку, є і ризики низькоякісного коду. Оскільки C # менш вимогливий до розробника, ймовірність появи коду низької якості на С # в середньому вища, ніж у випадку С++. При критичній масі такого коду це може створити серйозні проблеми в роботі програми.
У випадку З++ ситуація з низькоякісним кодом дещо краща, оскільки шанси на виживання у поганого коду нижчі, проте панацеєю від поганого коду С++ звичайно не є.
9. Самодостатність програм
Повної самодостатності програм немає ні у C++ ні у C #. Для C++ так чи інакше потрібен runtime, а для C # .net framework.
Однак хотілося б зазначити, що рантайм С++, як і будь-яка інша бібліотека, може бути статичний лінкований у виконуваний модуль, таким чином виконуваний модуль може містити все необхідне для роботи, і за рахунок чого стане самодостатнім, у випадку С # таке, стандартними засобами не реалізовується.
10. Зручність збірки
Збірка C++ проектів помітно складніша за збірку проектів С #. Однак варто розуміти, що велика складність надає і додаткову гнучкість, яка рано чи пізно може стати корисною вам. Правда до цього моменту буде лише збільшувати витрати вашого часів'яни.
11. Перспективи
Міркування про перспективи це завжди спекуляція. На сьогодні і С++ і C # активно розвиваються (хоча С++ почав активно розвиватися не так давно) Однак що буде далі?
Мене насторожує факт того, що темпи зростання продуктивності процесорів (принаймні в розрахунку на ядро) помітно знизилися і навряд чи в найближчому майбутньому ми побачимо їх істотне зростання. Те ж саме, думаю, можна сказати і про продуктивність введення-висновку.
Все це, швидше за все, створить запит на оптимізацію програмних продуктів і запит на паралельні обчислення. Я відчуваю деякий скептицизм щодо того, чи зможе С # задовольнити всі ці запити.
Висновки
Не можу сказати, що є універсальна відповідь на питання «З++ або ж С # використовувати для чергового проекту?», однак же можу сказати, що в різні періоди своєї діяльність я б по різному відповідав на питання про вибір, і якщо років 5 тому я б не розглядав C++ як кращий вибір, то зараз у більшій кількості випадків схилюся до того, щоб використовувати його. Однак, думаю, що для швидкого прототипування під Windows C # є і, можливо, буде кращим рішенням щодо С++.