Чи є якісь причини використовувати C ++ замість C, Perl, Python тощо? [зачинено]


164

Як розробник Linux (на стороні сервера), я не знаю, де і навіщо використовувати C ++.

Коли я збираюся виступити, перший і останній вибір - це C.

Коли "продуктивність" не є основною проблемою, хорошими варіантами стануть мови програмування, такі як Perl та Python.

Майже всі програми з відкритим кодом, які мені відомі в цій області, написані на C, Perl, Python, Bash script, AWK або навіть PHP, але ніхто не використовує C ++.

Я не обговорюю інші сфери, такі як GUI або веб-додатки, я просто говорю про Linux, CLI та демон.

Чи є якісь задовільні причини використовувати C ++?


5
Я вважаю лише C ++ через STL.
dan_waterworth

46
Тож те, що можна зробити за допомогою C, perl та python разом, можна зробити лише за допомогою C ++. А ви запитуєте, навіщо використовувати C ++?
Маной R

36
«Коли я збираюся виступити, перший і останній вибір - це C.» так впевнено: D Це недоведене і тривіально неправильне твердження.
deadalnix

16
@deadalnix: Я б не сказав цього. У C ++ є складні правила, які можуть призвести до запуску оптимізатора, оскільки робити це не дозволяється. І дуже легко вступити в невидимі вбивці продуктивності. Це в значній мірі аксіоматичний, і тому правдивий: D Все-таки в дійсності код C ++ іноді буде швидшим, оскільки ви будете використовувати більш ефективні алгоритми та структури даних, і ніхто фактично не оптимізує код C. Таким чином, якщо зробити все правильно, C ++ є безпечнішим та ефективнішим C, і вам слід вибрати C ++ над C, коли немає проблем із сумісністю або вимоги до програмного забезпечення на 100%.
Кодер

4
Найкраща причина, не розглянута у розміщених відповідях, безпосередньо стосується питання ОП. ЗАВИСИМОСТИ !!!!, Не те, що у вашої середньої системи не вистачає ліжок c ++, але вбудована система може не мати їх доступними. Єдиний спосіб отримати свою програму в кожній системі - це писати свою програму в звичайній С. Все інше - це лише дискусія, чому ви повинні або менш представлені не повинні використовувати C ++. Жодне з цих питань не стосується того, чому C ++ не використовується частіше, і незалежно від достоїнств, причиною є залежності .... О, а також відомий c ++ рент Лінуса.
Дж. М. Бекер

Відповіді:


308

Коли я збираюся виступити, перший і останній вибір - це C.

І ось тут слід створити резервну копію. Тепер, я не можу, взагалі , говорити на розвиток сервера. Можливо, насправді немає переконливих причин віддавати перевагу C ++ над альтернативами.

Але загалом кажучи, причиною використання C ++, а не інших мов, є насправді продуктивність. Причиною тому є те, що C ++ пропонує засоби абстракції, які не мають, на відміну від усіх інших мов, які я знаю, не забезпечують рентабельності продуктивності під час виконання.

Це дозволяє писати дуже ефективний код, який все ще має дуже високий рівень абстракції.

Розглянемо звичайні абстракції: віртуальні функції, покажчики функцій та ідіома PIMPL. Усі вони покладаються на непрямість, яка під час виконання вирішується арифметикою вказівника. Іншими словами, вона несе вартість продуктивності (наскільки вона невелика).

C ++, з іншого боку, пропонує механізм опосередкування, який не вимагає (продуктивності) вартості: шаблони. (Ця перевага виплачується за рахунок (іноді надзвичайно) збільшення часу компіляції.)

Розглянемо на прикладі загальної функції сортування.

У C функція qsortприймає функціональний вказівник, який реалізує логіку, за допомогою якої елементи упорядковуються відносно один одного. Arrays.sortФункція Java має декілька варіантів; один з них сортує довільні об'єкти і вимагає Comparatorпередачі йому об'єкта, який працює так само, як функція вказівника у C's qsort. Але є ще кілька перевантажень для «рідних» типів Java. І у кожного з них є своя копія sortметоду - жахливе дублювання коду.

Java ілюструє тут загальну дихотомію: або у вас є дублювання коду, або ви зазнаєте накладних витрат на виконання.

У C ++ sortфункція працює так само, як і qsortв C, з однією невеликою, але принциповою різницею: компаратор, який передається функції, є параметром шаблону . Це означає, що його дзвінок може бути накреслений . Для порівняння двох об'єктів не потрібно ніякого опосередкування. У тісному циклі (як це відбувається у нас) це насправді може суттєво змінитись.

Не дивно, що sortфункція C ++ перевершує C, sortнавіть якщо базовий алгоритм однаковий. Це особливо помітно, коли фактична логіка порівняння дешева.

Зараз я не кажу, що C ++ є апріорі ефективнішим, ніж C (або іншими мовами), а також, що він апріорі пропонує більш високу абстракцію. Те, що він пропонує, - це абстракція, яка є дуже високою і одночасно неймовірно дешевою, так що вам часто не потрібно обирати ефективний і багаторазовий код.


16
Зараз я знаю достатньо про C ++, щоб знати, чи ви помітили, чи не так. Але також хочемо додати, що ви отримали лише 1 потік, тому розслабтесь. Це Інтернет та знижки. Хоча чудова відповідь, якщо це технічно справно!
Кріс

46
відсутність накладних витрат на час виконання - це не завжди так. Якщо ви подивитеся на реалізацію векторів STL, ви побачите, що вони не користуються перевагою використання realloc () (вони не можуть через покажчики, довгу історію), тоді як усі мови вищого рівня, які я знаю, можуть використовувати і реально ( ) у векторних імпл. Це лише один приклад того, що це не так очевидно і все чорно-біле.
mojuba

19
@Jaroslaw, @Steve: але те ж саме (= розширення коду, кеш-інструкція пропускає) справедливо для оптимізованого вручну коду, адаптованого для кожного типу даних (див. Різні Arrays.sortреалізації Java ). Тільки ви втрачаєте перевагу високої абстракції. Це не специфічний недолік шаблонів, це недолік дублювання коду взагалі. Крім того, це, як правило, не має значення, оскільки у вузьких петлях завантажується завжди той самий код.
Конрад Рудольф

18
@Jaroslaw: найцікавіше в кеші інструкцій - це кеш . Тобто він не намагається зберігати все , лише нещодавно використаний код . Шаблони можуть генерувати безліч подібних кодів для різних типів (a vector.push_backдля vector<int>, а інший для vector<float>, але під час роботи з a vector<int>мало причин, чому цей vector<float>код буде в кеш-інструкціях. Тому я не бачу, як це насправді має значення. Кожен Індивідуалізація окремих шаблонів є оптимізованою та, як правило, більш компактною, ніж загальна реалізація всіх
прийомів

29
@ Steve314: Те, що ви називаєте "роздуттям", - це те, що робиться вручну для C та Java. У C ++ це може бути автоматизовано, і компілятори можуть бути такими ж розумними, як і виробники наважуються змусити їх уникнути роздуття. Якщо мені доведеться вирішити між повільністю (як у C) або використовувати дублюючий код (як у Java), то компілятор робить дублювання (і, можливо, розумний з цього приводу) здається досить гарним, ні?
sbi

166

Я бачу занадто багато програмістів на C, які ненавидять C ++. Мені знадобилося досить багато часу (років), щоб повільно зрозуміти, що добре, а що погано. Я думаю, що найкращий спосіб сформулювати це:

Менший код, відсутність накладних витрат, більша безпека.

Чим менше коду ми пишемо, тим краще. Це швидко стає зрозумілим у всіх інженерів, які прагнуть до досконалості. Ви виправляєте помилку в одному місці, не дуже багато - ви висловлюєте алгоритм один раз і повторно використовуєте його в багатьох місцях і т. Д. У греків навіть є приказка, простежена до стародавніх спартанців: "сказати щось менше словами, означає що ти мудрий у цьому ". І справа в тому, що при правильному використанні C ++ дозволяє висловити себе в набагато меншому коді, ніж на C, не витрачаючи на швидкість виконання, при цьому більш безпечно (тобто вловлюючи більше помилок під час компіляції), ніж C.

Ось спрощений приклад мого рендерінга : При інтерполяції значень пікселів по лінії трикутника. Я повинен почати з координати X x1 і досягти координати X x2 (зліва в праву частину трикутника). І через кожен крок, через кожен піксель, який я передаваю, я повинен інтерполювати значення.

Коли я інтерполюю зовнішнє світло, яке досягає пікселя:

  typedef struct tagPixelDataAmbient {
      int x;
      float ambientLight;
  } PixelDataAmbient;

  ...
  // inner loop
  currentPixel.ambientLight += dv;

Коли я інтерполюю колір (називається відтінком "Горо", де поля "червоний", "зелений" та "синій" інтерполюються на значення кроку на кожному пікселі):

  typedef struct tagPixelDataGouraud {
      int x;
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  } PixelDataGouraud;

  ...
  // inner loop
  currentPixel.red += dred;
  currentPixel.green += dgreen;
  currentPixel.blue += dblue;

Коли я рендерую в затінку "Phong", я більше не інтерполюю інтенсивність (ambientLight) або колір (червоний / зелений / синій) - я інтерполюю нормальний вектор (nx, ny, nz), і на кожному кроці я повинен повторно -розрахувати рівняння освітлення на основі інтерпольованого нормального вектора:

  typedef struct tagPixelDataPhong {
      int x;
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  } PixelDataPhong;

  ...
  // inner loop
  currentPixel.nX += dx;
  currentPixel.nY += dy;
  currentPixel.nZ += dz;

Тепер першим інстинктом програмістів на C було б "хек, запишіть три функції, які інтерполюють значення, і викликайте їх залежно від заданого режиму". Перш за все, це означає, що у мене є проблема типу - з чим я працюю? Чи мої пікселі PixelDataAmbient? PixelDataGouraud? PixelDataPhong? О, чекайте, каже ефективний програміст C, використовуйте союз!

  typedef union tagSuperPixel {
      PixelDataAmbient a;
      PixelDataGouraud g;
      PixelDataPhong   p;
  } SuperPixel;

..і тоді ви маєте функцію ...

  RasterizeTriangleScanline(
      enum mode, // { ambient, gouraud, phong }
      SuperPixel left,
      SuperPixel right)
  {
      int i,j;
      if (mode == ambient) {
          // handle pixels as ambient...
          int steps = right.a.x - left.a.x;
          float dv = (right.a.ambientLight - left.a.ambientLight)/steps;
          float currentIntensity = left.a.ambientLight;
          for (i=left.a.x; i<right.a.x; i++) {
              WorkOnPixelAmbient(i, dv);
              currentIntensity+=dv;
          }
      } else if (mode == gouraud) {
          // handle pixels as gouraud...
          int steps = right.g.x - left.g.x;
          float dred = (right.g.red - left.g.red)/steps;
          float dgreen = (right.g.green - left.a.green)/steps;
          float dblue = (right.g.blue - left.g.blue)/steps;
          float currentRed = left.g.red;
          float currentGreen = left.g.green;
          float currentBlue = left.g.blue;
          for (j=left.g.x; i<right.g.x; j++) {
              WorkOnPixelGouraud(j, currentRed, currentBlue, currentGreen);
              currentRed+=dred;
              currentGreen+=dgreen;
              currentBlue+=dblue;
          }
...

Чи відчуваєте ви, що хаос прослизає?

Перш за все, одна помилка - це все, що потрібно для збою мого коду, оскільки компілятор ніколи не зупинить мене в розділі функції "Gouraud", щоб фактично отримати доступ до ".a". (навколишнє) значення. Помилка, яка не потрапила в систему типу C (тобто під час компіляції), означає помилку, яка виявляється під час виконання і вимагатиме налагодження. Ви помітили, що я отримую доступ left.a.greenдо обчислення "дгрена"? Компілятор напевно не сказав вам цього.

Потім повсюдно є повторення - forцикл існує стільки разів, скільки є режими візуалізації, ми продовжуємо робити "правий мінус лівий, розділений на кроки". Некрасивий і схильний до помилок. Ви помітили, що я порівнюю, використовуючи "i" в циклі Гуро, коли я повинен був використовувати "j"? Компілятор знову мовчить.

А як щодо if / else / драбин для режимів? Що робити, якщо я додам новий режим візуалізації через три тижні? Чи пам’ятаю я обробляти новий режим у всьому «if mode ==» у всьому моєму коді?

Тепер порівняйте вищевказану потворність із цим набором структур C ++ та функцією шаблону:

  struct CommonPixelData {
      int x;
  };
  struct AmbientPixelData : CommonPixelData {
      float ambientLight;
  };
  struct GouraudPixelData : CommonPixelData {
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  };
  struct PhongPixelData : CommonPixelData {
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  };

  template <class PixelData>
  RasterizeTriangleScanline(
      PixelData left,
      PixelData right)
  {
      PixelData interpolated = left;
      PixelData step = right;
      step -= left;
      step /= int(right.x - left.x); // divide by pixel span
      for(int i=left.x; i<right.x; i++) {
          WorkOnPixel<PixelData>(interpolated);
          interpolated += step;
      }
  }

А тепер подивіться на це. Ми більше не робимо союз типу суп: у кожного режиму є конкретні типи. Вони повторно використовують свої загальні речі (поле "х"), успадкувавши від базового класу ( CommonPixelData). І шаблон змушує компілятор СТВОРИТИ (тобто генерувати код) три різні функції, які ми написали б самі в C, але в той же час, будучи дуже суворими щодо типів!

Наш цикл у шаблоні не може шукати та отримувати доступ до недійсних полів - компілятор буде бракувати, якщо ми це зробимо.

Шаблон виконує загальну роботу (цикл, щоразу збільшуючись на "крок"), і може робити це таким чином, що просто НЕ МОЖЕ викликати помилки виконання. Інтерполяція по типу ( AmbientPixelData, GouraudPixelData, PhongPixelData) робляться з , operator+=()що ми додамо в структурах - які в основному диктують , як інтерполюються кожен тип.

І чи бачите ви, що ми робили з WorkOnPixel <T>? Ми хочемо робити різні роботи для кожного типу? Ми просто називаємо шаблонну спеціалізацію:

void WorkOnPixel<AmbientPixelData>(AmbientPixelData& p)
{
    // use the p.ambientLight field
}


void WorkOnPixel<GouraudPixelData>(GouraudPixelData& p)
{
    // use the p.red/green/blue fields
}

Тобто - функція викликати, вирішується виходячи з типу. Під час компіляції!

Щоб перефразовувати його ще раз:

  1. ми мінімізуємо код (за допомогою шаблону), використовуючи загальні частини,
  2. ми не використовуємо некрасиві хаки, ми тримаємо сувору систему типу, щоб компілятор міг перевіряти нас у будь-який час.
  3. і найкраще: жодне з того, що ми зробили, не впливає на виконання будь-якого часу. Цей код запуститься ДІЙКІСТЬ так само швидко, як і еквівалентний код C - адже, якщо C код використовував функціональні покажчики для виклику різних WorkOnPixelверсій, код C ++ буде Швидше C, оскільки компілятор буде вбудовувати WorkOnPixelспеціалізовану спеціалізацію шаблону дзвоніть!

Менший код, відсутність накладних витрат, більша безпека.

Чи означає це, що C ++ - це мовна система для всіх і кінцевих? Звичайно, ні. Ви все ще повинні оцінювати компроміси. Невідомі люди використовуватимуть C ++ тоді, коли вони повинні були написати сценарій Bash / Perl / Python. Новачки C ++, що спричиняють тригери, створять глибокі вкладені класи з віртуальним багатократним успадкуванням, перш ніж ви зможете зупинити їх та відправити їх упаковкою. Вони будуть використовувати складні метапрограмування Boost, перш ніж зрозуміти, що це не потрібно. Вони будуть по- , як і раніше використовувати char*, strcmpі макроси, а std::stringй шаблони.

Але це не означає нічого іншого, як ... дивіться, з ким ви працюєте. Немає мови, щоб захистити вас від некомпетентних користувачів (ні, навіть Java).

Продовжуйте вивчати та використовувати C ++ - просто не передумуйте.


18
+1 за "ні, навіть не Java" :)
Натан Осман

53
+1 для прикладу. Це був довгий пост, але порівняння між кодом C та C ++ вражає.
paercebal

І ось це, панове, панове, тому існує lex / yacc. За тими ж міркуваннями, я ніколи не розумів, що частини c ++ потрапляють у ту саму філософію генерації коду. Мені доведеться коли-небудь ще раз поглянути на це.
Спенсер Ратбун

2
Я написав безліч двовимірного коду візуалізації (більше десяти років тому) і зіткнувся з цією проблемою під час перенесення з C на C ++: як ви визначаєте структуру пікселів, якщо сканування зроблено з 1-бітових пікселів (8 пікселів у байт)? А коли ваш сканер складається з байтів R, G і B (3 байти на піксель)? А коли у вас є три окремих буфера для R, G і B? Ви знаєте відповідь: C ++ тут ​​не допомагає, і наполягаючи на використанні шаблонів, ви втратите багато оптимізації простору та часу
Walter Tross

Чому для цього ви використовуєте шаблони в C ++? Ваш метод декларує параметр базового класу, тому з моєї точки зору [програміст C #] він виглядає так, що ви можете просто передати екземпляр похідного типу параметру базового типу. Я не знаю С ++, ви можете пояснити, будь ласка?
Влад

79

РАЙ для виграшної дитини.

Серйозно, детерміновані знищення в C ++ роблять код набагато чіткішим та безпечнішим, без будь-яких накладних витрат.


20
"C ++: Єдиний серйозно детермінований варіант. Запитайте про це свого лікаря сьогодні".
Кайл Странд

2
Наступні дії: Руст зараз є претендентом у цій галузі. Дивіться основний приклад RAII та документацію про методи руйнування Руста .
Кайл Странд

1
C буде таким же детермінованим, але вимагає більше роботи, щоб переконатися, що це насправді трапляється при використанні малопомітної пам’яті
Baldrickk

1
@Baldrickk в C ви повинні писати код очищення скрізь, де ви використовуєте ресурс. У C ++ ви пишете це один раз , у визначенні ресурсу. І C, і Java страждають від помилок "ресурс, який використовується після утилізації" та "витік ресурсу", оскільки очищення не є автоматичним . Пам'ять - не єдиний ресурс.
Калет

70

Чи є якась задоволена причина використовувати C ++?

  1. Шаблони та STL. Ви торгуєте невеликим часом побудови (і деякими потенційно незрозумілими повідомленнями про помилки) для багатьох корисних інструментів абстрагування та економії праці, не маючи помітних результатів роботи (хоча бінарний слід може бути трохи більшим).

    Потрібно зайняти деякий час, щоб обернути голову (мені знадобилося пару років, перш ніж вона натиснула), але коли ви це зробите, це може зробити життя набагато простішим.

  2. Обробка тексту в С ++ на порядок менше болісна, ніж у С.


35
+1 для обробки тексту, про яку я повністю забув у своїй відповіді.
Конрад Рудольф

8
Хе, я вважав, що обробка тексту особливо болісна в порівнянні, скажімо, з Python ..
Nils

7
Підвищення - це єдина причина, по якій я все ще використовую C ++.
Ферруччо

33
@Nils: За шкалою від 1 до болю в дупі, обробка тексту на C ++, безумовно, гірша, ніж у сучасних мовах, таких як Python. Просто обробка тексту на C визначає біль у дупі. Якщо для конкретного додатка вибір між C і C ++, тоді C ++ виграє легко.
Джон Боде

8
Я не знаю, чому люди мають такі труднощі з такими речами, як обробка тексту на C / C ++. Просто скористайтеся бібліотекою або напишіть свою. Після того, як ви написали функції низького рівня (одноразовий біль), ви отримаєте масивну ефективність, чіткий код та більшу гнучкість. Так, я буду використовувати Python для швидких / брудних утиліт командного рядка, але для серйозного виробничого коду його C / C ++.

41

Так.

Якщо ви шукаєте ефективність виконання файлів, ви переходите на C або C ++, тому я зупинюся на цьому.

Ще до того, як шаблони були загальними, я вважав за краще використовувати C ++ над C для тих типів виконуваних файлів, про які ви обговорювали ще в середині 1990-х, з двох дуже простих причин: поліморфізм об'єкта та RAII .

Я використовував поліморфні об’єкти C ++ для всіляких цікавих речей. Наприклад, я працював над вбудованою системою Linux з накладками буфера кадру на процесорах OMAP та XScale ARM. Дві апаратні архітектури мають різні функції накладання з дуже різними API. Я використовував загальний віртуальний базовий клас "Накладення", щоб викрити ідеалізований вигляд накладок, а потім написав класи "OmapOverlay" та "XScaleOverlay", які були піддані належній інстанції під час виконання, залежно від того, на якій архітектурі виявлено код, на якому він працює.

Щоб спростити, RAII - це ідея, що ви виділяєте ресурси, підключені до об'єкта під час конструктора об'єкта, або, можливо, пізніше протягом життя об'єкта, і ресурси дістаються або звільняються в деструкторі об'єкта. Це дійсно добре в C ++, тому що об'єкти, які є автоматичними змінними, руйнуються, коли вони виходять за межі області. Для тих, хто однаково компетентний на C та C ++, набагато простіше уникнути витоків ресурсів та пам’яті на C ++. Ви також не бачите великого коду C ++ з дуже поширеним пам'яткою C ярлика в кінці функції, що передує купі викликів free(), і різних gotoперелічених у функціональному блоці скачучих туди.

Я цілком усвідомлюю, що ви можете робити всі ці речі за допомогою C - це просто набагато більше роботи, більше рядків коду, і те, що ви закінчуєте, набагато гірше і часто важче зрозуміти. Код поліморфізму є в усьому внутрішньому середовищі сервера X , і людина, хіба це дивно і дивно і часто важко простежити.

Я також багато працюю з такими технологіями GNOME, як GTK + та Clutter, які написані на C за допомогою системи GObject. GObject - це як об'єктна система C ++ з приємною знятою обкладинкою та відкритими усіма некрасивими внутрішніми внутрішніми елементами, і зазвичай потрібно півдесятка рядків коду, щоб зробити те, що буде робити однолінійний дзвінок методу C ++. Я зараз пишу деякі ClutterActors, і хоча математика справді цікава, я постійно думаю: "Це все було б набагато більш лаконічним і зрозумілим на C ++".

Я також часто думаю: "Ви знаєте, якби я писав це на C ++ замість C, я був би у вітальні, спостерігаючи за MythBusters зі своєю дружиною, а не сидів у своєму кабінеті о 21 вечорі".


9
Я справді можу сказати про те, що ви тут говорите, особливо 1) пункт про RAII та 2) думка "Ви знаєте, якби я писав це на C ++ замість C ..." Я роблю багато розробок вбудованих систем , і навіть якщо команда в крамниці є магазином "C" або "C з класами", я дійсно намагаюся заохотити RAII до таких речей, як маніпуляції з перериванням, операції з мютексами та відстеження / ведення журналів (наприклад, такі як перемикання вводу / виводу лінії). А ваш опис поліморфних буферів кадру нагадав мені про моє використання поліморфних буферів повідомлень у розподіленій системі.
Радіан

29

C ++ працює приблизно так само швидко, як і C (деякі речі швидше, а інші повільніше), і вони пропонують кращі абстракції та організацію. Класи працюють аналогічно примітивним типам, дозволяючи використовувати велику кількість коду, не маючи на увазі. Перевантаження і шаблони оператора дозволяють писати код, який функціонує краще, якщо представлення даних змінюється. Винятки можуть дозволити простіше поводження з помилками. Компілятор можна використовувати для перевірки більше матеріалів під час компіляції.

Ціна, яку ви платите за це, є досить неприємною кривою навчання, і в ній легше робити тонкі помилки, ніж більшість інших мов, з якими я знайомий.

Тож я не можу сказати, чи варто було б тобі навчитися тому, що ти зараз робиш. Ви, звичайно, можете досягти комбінацій Python або Perl і C, але C ++ пропонує як абстракцію, так і продуктивність в одному важкодоступному пакеті.


13
Там немає ні випадку , в якому C ++ повільніше , ніж C , тому що ви завжди можете використовувати C шлях , якщо він швидше (і ви піклуєтеся).
Джек Едлі

1
@JackAidley - За винятком того, що C ++ не підтримує параметри обмеження та статичного масиву. І крім того, що використання C ++-стилю в одному місці змушує вас використовувати його в інших місцях.
мартінкунев

@martinkunev restrictвикористовується для виключення з оптимізації, так як це допомагає зробити все швидше ? і що таке "параметр статичного масиву"? і як "стиль" впливає на продуктивність?
підкреслюй_d

1
@underscore_d обмеження дозволяє оптимізувати, виходячи з гарантії на нежиття; параметри статичного масиву дозволяють компілятору припустити, що аргумент вказівника не NULL і що цей вказівник вказує принаймні на задану кількість елементів; слово "стиль" має кілька значень, і виведення його з контексту змінює його значення - я говорю про те, як, наприклад, винятки примушують використовувати розумні покажчики.
мартінкунев

1
@martinkunev Хм, тому мені цікаво, чи параметр статичного масиву дозволяє щось функціонально відрізнятися від шаблону C ++ з використанням T (&arr)[n]або std::array<T, n>- доведеться вивчити цей ще один, оскільки там не так багато інформації. Це має сенс щодо розумних покажчиків, безумовно, хороший приклад. Якщо кодування на рівних ігрових полях, ми б не використовували винятку, тому жодна з потенційних витрат не була б понесена… однак, я підозрюю, що ви можете натякати на те, як, коли сторонні бібліотеки увійдуть у зображення, багато припущень ризикують.
підкреслити_22

27

Я розглядаю С ++ як мову 1990-х, мову минулої епохи.

Тоді воно було великим, оскільки пропонувало мовні конструкції та механізми вищого рівня за меншими витратами з точки зору продуктивності. Це був універсальний інструмент для розробки всього, починаючи від додатків адресної книги до програмного забезпечення авіоніки, і це надихнуло манеру OO OOP вирішив голод та СНІД, і так, я звинувачую С ++ у тому, що він намагався промити мізки в кінці 1990-х, коли я вперше почав програмувати, що будь-яку мову, яка не є ОО - вивчати не варто.

Тепер, коли апаратне забезпечення настільки розвинене, і з’явилися новіші сучасні мови, я не бачу, щоб C ++ залишався релевантним вибором для більшості прикладних програмувань, за винятком обчислювально інтенсивного програмного забезпечення, де ще потрібна абстракція (ігри, фізичні симуляції, системи САПР тощо). ). Навіть останнього можна уникнути, якщо ви пишете компактний, модульний двигун на C і маєте логіку додатків вищого рівня, делеговану на акуратну мову сценаріїв.

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


11
Тому не змінюйте випадкові байти за допомогою покажчиків. Цього не так складно уникнути, чи не так?
Девід Торнлі

11
@Blagovest: Я згоден з вами щодо складності C ++, і я ніколи не використовував би її для заміни об'єктно-орієнтованої мови. Але, незважаючи на складність, він все-таки перемагає для мене C через безліч переваг, прописаних у різних відповідях (абстрагування, передача ресурсів, обробка рядків…). Насправді ви назвали кілька дійсних областей, де C ++ все ще є актуальним, і де він набагато перевершує C.
Конрад Рудольф

6
@Blagovest: Тому я тримаюся поза темними куточками. Тут простіше зануритися на C ++, ніж будь-яка інша мова, яку я знаю. Використовуючи його, я отримую перевагу від RAII, набагато кращого керування рядками, ніж C, класи шаблону типу STL, функції OO та інші переваги, які він має над C.
Девід Торнлі

24
@Blagovest: Ні, ви цього не робите. Наприклад, те, що ви згадали, недостатнє для досягнення RAII, а класи контейнерів мають функціональність, що виходить за рамки простих вручну складених структур даних. Якщо ви думаєте, що це можливо, ви ніколи не засвоювали C ++.
Девід Торнлі

5
@Jaroslaw Я не розумію, чому багатоядерні машини поставлять OOP на могилу. Якщо ви маєте на увазі C ++, я можу побачити, звідки ви родом. OOP - фундаментальна концепція багатьох сучасних мов програмування, особливо мов високого рівня. Навіть C може бути OO, якщо ви програмуєте його таким чином. Це просто не так зручно, як C ++ IMO.
vedosity

21

За словами Лінуса , ні:

Коли я вперше подивився на вихідний код Git, дві речі мені здалися дивними: 1. Чистий C на відміну від C ++. Не знаю чому. Не кажіть про портативність, це BS.

ВИ повні дурниць.

C ++ - жахлива мова. Це стало жахливішим завдяки тому, що багато хто з нестандартних програмістів використовує його, до того моменту, коли набагато простіше генерувати тотальне і повне лайно з ним. Відверто кажучи, навіть якщо вибір C мав би нічого не робити, крім того, щоб утримати програмістів C ++, це саме по собі було б величезним приводом для використання C.

Іншими словами: вибір C - єдиний розумний вибір. Я знаю, що Майлз Бадер жартівливо сказав: "щоб тебе злізли", але насправді це правда. Я прийшов до висновку, що будь-який програміст, який вважає за краще, щоб проект був у C ++ над C, швидше за все, програміст, якого я дійсно вважав би за краще піклуватися, щоб він не приходив і не накручував жодного проекту, який я брав до участі з.

C ++ призводить до дійсно поганого дизайнерського вибору. Ви незмінно починаєте використовувати "приємні" функції бібліотеки такої мови, як STL та Boost, та інших повних і повних ганьб, які можуть "допомогти" програмі, але викликають:

  • нескінченна кількість болю, коли вони не працюють (і той, хто мені каже, що STL і особливо Boost є стабільними та портативними, просто настільки BS, що це навіть не смішно)

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

Іншими словами, єдиний спосіб зробити хороший, ефективний та портативний C ++ на портальному рівні, це обмежити себе всіма речами, які є в основному в C. А обмеження вашого проекту на C означає, що люди не гріплять це вгору, а також означає, що ви отримуєте багато програмістів, які насправді розуміють проблеми низького рівня і не накручують справи з будь-якими ідіотичними лайнами "об'єктної моделі".

Так що мені шкода, але для чогось типу git, де ефективність була головною метою, "переваги" C ++ - це просто величезна помилка. Той факт, що ми також жаліємо людей, які не бачать цього, є лише великою додатковою перевагою.

Якщо ви хочете VCS, записаний на C ++, перейдіть пограти з Monotone. Дійсно. Вони використовують "реальну базу даних". Вони використовують "приємні об'єктно-орієнтовані бібліотеки". Вони використовують "приємні абстракції C ++". І, відверто кажучи, в результаті всіх цих дизайнерських рішень, які звучать настільки привабливо для деяких людей з КС, кінцевим результатом стає жахливий і незрозумілий безлад.

Але я впевнений, що вам це сподобається більше ніж git.

      Linus

62
Я не думаю, що Лінус повинен бути хлопцем, до якого слід звернутися до аргументів. Його зухвали жахливо суб’єктивні та незрілі. Насправді у нього є кілька хороших моментів, але вони настільки глибоко закопані (внизу «фігня», а також фігня), що їх важко знайти.
Конрад Рудольф

19
Ха-ха, це був гарний сміх. Я ніколи не хочу зустрічатися з цим хлопцем.
Фелікс Домбек

30
Лінус нагадує мені дуже талановитого покрівельника, який ніколи не підвішував профнастилу, але називає хлопців-листовців штанами, бо замість цвяхів використовує гвинти.
Боб Мерфі

8
У Лінуса є пункт, але він висловлює надто суворо, щоб його сприймати серйозно.
Благовест Буюклієв

39
Я погоджуюся з @Daniel. Якщо є хтось, хто може говорити про просування меж апаратних засобів, це Джон Кармак, творець дум, землетрусів та інших ігор та засновник програмного забезпечення Id. Він пише це про c і c ++ у twitt кілька місяців тому: "IMO, хороший код C ++ є кращим, ніж хороший код C, але поганий C ++ може бути набагато, набагато гіршим, ніж поганий код C". twitter.com/#!/ID_AA_Carmack/status/26560399301
Onema

18

Я не думаю, що немає жодних вагомих причин використовувати C ++. Якщо ви хочете зайнятися програмуванням OO, ви можете використовувати замість цього Python і записати частини, які потребують швидкої продуктивності у C.

EDIT: Є й інші мови, які добре взаємодіють із C, тому якщо вам не подобається Python, є альтернативи.


3
Що з вбудованою розробкою? Python не завжди доступний, і різниця у швидкості між C і добре написаною C ++ незначна на пристроях, що перевищують певний рівень потужності обробки. Звичайно, я вважаю, що компілятор C ++ також не завжди буде доступний ...
Джеймс,

6
@James "добре написаний C ++" - є улов :(
dss539

5
Я погоджуюся з цією відповіддю: зробіть високий рівень з python, оскільки ви напишете це на кшталт 3 рази швидше, профіліруйте, а потім випустіть вузькі місця, замінивши їх на C / C ++. Зайве сказати «замінити вузьке місце на код C ++», оскільки ви не зробите будь-якого високого рівня з кодом, який вам потрібно бути швидким, оскільки це буде код низького рівня. Є одне: я не знаю, як інтерфейс c ++ з python: /. але з точки зору часу, проведеного перед екраном та ефективністю, я думаю, що це найкраще рішення, оскільки більшість кодів C ++ буде швидким ні за що!
jokoon

8
Попрацюйте у великій фінансовій компанії та побудуйте складну фінансову систему у великій розподіленій команді в Python і подивіться, як вам це подобається. Досвід навчить вас: а) переваги безпеки типу, б) переваги компіляторів, що зберігають ваш зад, в) код LUDICROUS, який Python дозволяє нообам писати. Люди кажуть, що легко стріляти ногою за допомогою C ++ -> деякі речі з пітонів можуть спрацювати, але бути прикордонним божевіллям. Зараз я б настільки сильно працював у С ++ ...
MrFox

1
@suslik: Ого, я шокований, що хтось би насправді використовував python для такої системи. Я погоджуюсь з вами щодо поганого коду noob python; Я сам бачив деяких.
Ларрі Коулман

13

Чи є причина використовувати C ++? Звичайно.

Деякі люди можуть просто віддати перевагу використанню C ++ над іншими параметрами. Запитувати, чи є причина використовувати C ++, це як запитати, чому нам потрібно мати сотні ароматів морозива. Не всім подобається просто прилипати до ванілі.

Якщо розробники вже дуже компетентні щодо C ++, питання до них може бути не «навіщо це використовувати?», А швидше «чому ні?». Здається, зараз ця модна річ проти С ++ відбувається в ТАК, але вірите чи ні, не всі підписуються на це. Деяким людям просто подобається C ++ краще, ніж інші мови.

Чи потрібно використовувати C ++ для додатків? Звичайно, ні. Але це саме точне запитання можна задати і для будь-якої іншої мови. Є дуже-дуже мало випадків, коли для програми потрібно використовувати певні мови.


12

Я просто переходжу з C на C ++, і я думаю, що посилення є значним, навіть якщо у вас немає потреби в шаблонах і OOP.

  • Краще управління пам’яттю
  • Більш міцна система
  • Краща стандартна бібліотека
  • Простори імен
  • тощо.

8

Я здивований, що ніхто про це ще не згадав, але C ++ познайомив нас із посиланнями , які майже вирішують усі проблеми та підводні камері:

void ModifyVar(int& var)
{
    var = 5;
}

int test = 4;
ModifyVar(test);

Замість:

void ModifyVar(int * var)
{
    *var = 5;
}

int test = 4;
ModifyVar(&test);

Набагато безпечніше і простіше ... і без накладних витрат на проїзд.


3
Також набагато менш гнучким. Посилання (стиль C ++) добре спрощують певні поширені конструкції мовою, яка також має покажчики, але вони поки що не є заміною покажчиків, це навіть не смішно. І ваш приклад - зовсім не хороший випадок для довідок.
Бен Войгт

3
@Ben: Тоді ви можете пояснити, чому це поганий приклад?
Натан Осман

6
@George: Тому що нічого не змінилося, за винятком того, що два символи коротше? Це не вирішує жодних проблем, це не виділяє жодних підводних каменів, це навіть не робить нічого крутого, як би продовжити термін дії тимчасової змінної (на що посилаються добре).
Бен Войгт

@Ben: Ви щось забуваєте - посилання завжди діє. Покажчики можуть вказувати на що завгодно (включаючи NULL), що може призвести до різного роду помилок пам'яті, якщо все зроблено неправильно. Посилання ніколи не можуть бути NULL, а адресу, на яку вони вказують, ніколи не можна змінювати.
Натан Осман

5
@George: "посилання завжди дійсна" є неправдивою. Наведу приклад, якщо він вам потрібен, але я сподіваюся, що ви достатньо досвідчені, щоб уже знати про це. І я не говорю про формування недійсної посилання, використовуючи недійсний покажчик. Функції, які використовують покажчики, потребують документації із зазначенням передумов аргументів. Але практично кажучи, всі функції потребують такого рівня документації, тому абсурдно називати це ударом проти покажчиків.
Бен Войгт

5

Де і чому зазвичай збираються:

  • знайомство
  • бажані мовні особливості
  • конкретні бібліотеки, які ви хочете використовувати
  • вимоги до продуктивності

Для програмування на сервері часто можна вибрати безліч різних мов, складених або інтерпретованих. Зазвичай вибір мови визначається тим, на якій платформі ви чи ваша команда будете найбільш ефективними. Або якщо у вас ще немає команди, наявність навичок на ринку.

Що стосується бічної записки, я не дуже розумію рішення про використання C / C ++ на основі продуктивності (лише), оскільки багато мов сценаріїв можна розширити за допомогою C / C ++. Ви отримуєте перевагу мови швидкого розвитку, що поєднується із можливістю міграції повільних частин у розширення C / C ++. Звичайно, якщо ти робиш системи програмування, де кожна операція вважає, що це зрозуміло, але в більшості розробок додатків я цього не розумію.


2
Знайомство є причиною №1, і я здивований, що ви перший згадаєте про це.
Пол Різник

4

C ++ проти Python vs Perl не можна легко оцінити. Це залежить від проекту та вимог.

C ++ має арсенал утиліт з давніх-давен, що працює на багатьох платформах. Але боляче починати ходити по потоках для просто проходження String до Integer і назад.

З іншого боку, C ++ має жахливу справу із залежностями від бібліотек. Після того, як ви компілюєте щось у GCC X або VC ++ Y, ви не можете розраховувати, що код працюватиме наступною версією цих інструментів. Це ж пекло на Windows, таке ж пекло і на Unix.

Perl, переймає свою силу у світі Unix, але особливо як інструмент регулярного вираження. Це те, чим воно використовується більшість часу. Поряд із деякими досить серйозними інструментами, які навіть Java не можуть це зробити нормально (дізнайтеся, як завантажити файл на веб-сервер), Perl - це "просто зробіть це".

Python - це проста, гнучка та динамічна мова. Настільки просто, що ви можете відправити ціле число до функції, сценарій очікує рядок, але ви можете мати результат! Хоча несподівано, але результат. Тож програмісту потрібно бути дуже обережним. IDLE пропонує деякі налагодження, але коли у вас TELNET'ed в системі або SSH'ed на три рівні вниз і ви хочете знайти свою проблему, налагоджувач не буде стояти поруч з вами. Але, це може зробити велику математичну роботу швидко.

Java - це екосистема мовних слів, чужих технологій та великих слів, і коли ви хочете просто завантажити файл на веб-сервер, ви виявите, що це можна зробити, лише якщо на сервері є JSP . Якщо ви хочете зателефонувати в системні бібліотеки або такі системні функції, як моніторинг, ви виявите, що вам доведеться багато копати. І можливо, щоб дістатися до JNI і гаразд ... ти думаєш тоді ... "Чому, Господи?"

Крім того, Java - це чудовий інструмент для бізнес-пакетів, і багатопотокова робота мені дуже сподобалась.

Швидко складіть програму і покажіть своє резюме "О, я знаю, що і технологія", і ваш бажаючий начальник, дивуйтеся! Незважаючи на те, що технологія може бути не такою, яка потрібна ... (Гаразд, люди, я ненавиджу Spring Framework ....)


1
На жаль, ви повинні врахувати, що Python має залежність від версії - особливо коли ви переходите на Python 3, те саме з perl .. чи хтось ще не переймався переїздом на Perl 6? Все має неприємні залежності :(
gbjbaanb

3

Що потрібно пам’ятати, обираючи мову, полягає в тому, яку вигоду ви отримаєте від її використання та скільки часу знадобиться для її отримання.

Основна ідея між такими мовами, як python та perl, - це робити більше з меншою кількістю часу, але з більшім процесором. Насправді ви витратите більше часу на кодування сценарію python або perl, ніж це буде виконано, але ви зрозумієте мою думку.

Перевага C / C ++ полягає в тому, що вони швидкі, але ціною синтаксису та сильним набором тексту: вам доведеться багато робити самому, щоб комп’ютеру не довелося вибирати його під час компіляції.

Коли ви робите код, деякі рядки будуть проходити набагато більше, ніж інші, і ці рядки представляють проблему. З іншого боку, весь інший код, той, на який ви витратили багато часу, виконується набагато рідше. Можливо, ви це чули, але це сумнозвісне правило 80/20, і ви не зможете обійти таке правило.

Вирішення цієї проблеми полягає у використанні більш простої мови (під простішим, я маю на увазі більш зручну для розробників: менше набору тексту, лінивої інтерпретації, багато попередніх процедур та інших матеріалів тощо), щоб виконати весь свій код.

Ви зробите це так швидко порівняно з тим, якби ви зробили це за допомогою C або C ++, це зайняло б набагато більше головного болю.

Ваша програма буде повільною, але за допомогою профілера ви виділяєте частину, яку виконуєте 80% часу, і ви виконуєте їх за допомогою C або C ++.

Програмувавши таким чином, ви заощадили багато часу, а ваша програма настільки ж ефективна, як швидше, має набагато менші шанси витікати пам'ять, і ви заощадили час.

Мови сценаріїв були розроблені на стороні розробника, але оптимізація все ще можлива. Звичайно, ти можеш бути фокусником-дизайнером, вуду STL або навіть воїном, що може бути, і, можливо, ченцем хаскелл. Але мови змушують нас говорити з комп'ютерами, мови не створені для того, щоб ми були БЕЗ комп’ютерами!



2

C ++, який я використовую, називається C з класами!


8
Ура, ви використовували ключове слово "class". Тепер ви розумієте дизайн OO!
dss539

Мій C ++ називається C з просторами імен.
jsz

6
Мій C ++ називається, гмм .. C ++ Маноя.
Маной Р

+1 Класи - це єдина причина, чому я використовую C ++.
mbq

... ок, також винятки.
mbq

0

Насправді єдина відповідь на всі подібні запитання. Найкращий привід використовувати tech X замість tech Y (де X і Y приблизно на одному рівні [як і майже всі сучасні мови програмування]) - це те, що ви вже знаєте X і не знаєте Y.

(але після того, як Haskell приїхав, не було жодної причини використовувати щось інше)


0

Ні, зовсім ні. Якщо вам не потрібна продуктивність, і у вас є бібліотека, ви можете використовувати іншу мову, тоді не турбуйтеся з C / C ++. Я роблю це лише сьогодні, коли націлююсь на вбудовані системи, які не можуть (легко?) Запускати мови. Іноді я використовую C, тому що пишу плагін, але насправді ні.

Однак я б не використовував Python, Perl і т. Д., Щоб не використовувати C. Мої переваги - це фактично C #, тому що мені подобається хороша бібліотека (яка є силою .NET), і мені подобаються статично набрані мови. Бу - хороша альтернатива. Але насправді Haskell , OCaml , D , ML та подібні - все добре.


7
Ви пропустили точку.
Метт Столяр

@Matt Joiner: Я впевнений, що цього не зробив. Що я пропустив?

Питання в тому, щоб не використовувати C ++.
Метт Столяр

@Matt Joiner: Хм, по іншому погляді я бачу, що мене запитують. Але здається, що я теж відповів (я сказав, що не турбуйтеся і альтернативи, якими я користуюся)

Я майже хочу спростувати це через C # ...
Vreality
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.