Есть ли причина использовать C ++ вместо C, Perl, Python и т. Д.? [закрыто]

164

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

Когда я иду на выступление, первый и последний выбор - C.

Когда «производительность» не является главной проблемой, языки программирования, такие как Perl и Python, были бы хорошим выбором.

Почти все приложения с открытым исходным кодом, которые я знаю в этой области, были написаны на C, Perl, Python, скриптах Bash, AWK или даже PHP, но никто не использует C ++.

Я не обсуждаю другие области, такие как GUI или веб-приложения, я просто говорю о Linux, CLI и демонах.

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

Ehsan
источник
5
Я рассматриваю только C ++ из-за STL.
dan_waterworth
46
Так что то, что можно сделать, используя C, Perl и Python вместе, можно сделать только с помощью C ++. И вы спрашиваете, почему использовать C ++?
Маной Р
36
«Когда я иду на спектакль, первым и последним выбором является C.» Да, конечно: D Это бездоказательное и тривиально неверное утверждение.
Deadalnix
16
@deadalnix: я бы так не сказал. C ++ имеет сложные правила, которые могут иметь неприятные последствия для оптимизатора, потому что не разрешено делать некоторые вещи. И очень легко вступить в невидимых убийц производительности. Это в значительной степени аксиоматично и, следовательно, верно: D Тем не менее в действительности код C ++ иногда будет быстрее, потому что вы будете использовать более эффективные алгоритмы и структуры данных, и никто в действительности не оптимизирует код C в любом случае. Таким образом, если все сделано правильно, C ++ является более безопасным и более эффективным C, и вам следует выбирать C ++ вместо C, когда нет проблем с совместимостью или требования к 100% доступности программного обеспечения.
Кодер
4
Лучшая причина, не учтенная в опубликованных ответах, напрямую связана с вопросом ОП. ЗАВИСИМОСТЬ !!!! Не то чтобы в вашей обычной системе отсутствовали библиотеки c ++, но во встроенной системе они могут быть недоступны. Единственный способ получить вашу программу в каждой системе - это написать вашу программу на обычном C. Все остальное - просто спор, почему вы должны или менее представлены, не должны использовать C ++. Ничто из этого не объясняет, почему C ++ не используется чаще, и, независимо от достоинств, причина в зависимостях ... O, а также в знаменитой лексике Линуса c ++.
Дж. М. Беккер

Ответы:

308

Когда я иду на представление, первый и последний выбор - C.

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

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

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

Рассмотрим обычные абстракции: виртуальные функции, указатели на функции и идиома PIMPL. Все они основаны на косвенном обращении, которое во время выполнения разрешается арифметикой указателя. Другими словами, это влечет за собой снижение производительности (как бы мало это ни было).

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

Рассмотрим пример универсальной функции сортировки.

В C функция qsortпринимает указатель на функцию, которая реализует логику, по которой элементы упорядочены относительно друг друга. Arrays.sortФункция Java поставляется в нескольких вариантах; один из них сортирует произвольные объекты и требует, чтобы ему Comparatorбыл передан объект, который во многом похож на указатель на функцию в Си qsort. Но есть еще несколько перегрузок для «нативных» типов Java. И у каждого из них есть своя копия sortметода - ужасное дублирование кода.

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

В C ++ sortфункция работает так же, как qsortв C, с одним небольшим, но принципиальным отличием: компаратор, который передается в функцию, является параметром шаблона . Это означает, что его вызов может быть встроенным . Нет необходимости в косвенном сравнении двух объектов. В тесной петле (как в данном случае) это может существенно изменить ситуацию.

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

Теперь я не говорю, что C ++ априори более эффективен, чем C (или другие языки), и что он a priori предлагает более высокую абстракцию. Что он предлагает, так это абстракцию, которая очень высока и невероятно дешева в то же время, так что вам часто не нужно выбирать между эффективным и повторно используемым кодом.

Конрад Рудольф
источник
16
Теперь я знаю достаточно о C ++, чтобы понять, в чем дело или нет. Но также хочу добавить, что вы получили только 1 downvote, так что расслабьтесь. Это интернет и провалы происходят. Отличный ответ, хотя, если это технически звучит!
Крис
46
нет снижения производительности во время выполнения - это не всегда так. Если вы посмотрите на векторные реализации STL, то увидите, что они не пользуются преимуществами использования realloc () (они не могут из-за указателей, длинной истории), тогда как все языки более высокого уровня, которые я знаю, могут и действительно используют realloc ( ) в векторных импл. Это всего лишь один пример того, что он не так очевиден и все черно-белое.
Моджуба
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;

При рендеринге с затенением «Фонг» я больше не интерполирую интенсивность (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;

Теперь первым инстинктом программистов на Си будет «черт возьми, напиши три функции, которые интерполируют значения и вызывают их в зависимости от установленного режима». Прежде всего, это означает, что у меня есть проблема с типом - с чем я работаю? Являются ли мои пиксели 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;
          }
...

Чувствуете ли вы хаос?

Прежде всего, одна опечатка - это все, что нужно для сбоя моего кода, так как компилятор никогда не остановит меня в разделе функции «Гуро», чтобы фактически получить доступ к «.a». (окружающие) значения. Ошибка, не обнаруженная системой типов C (то есть во время компиляции), означает ошибку, которая проявляется во время выполнения и требует отладки. Вы заметили, что я обращаюсь left.a.greenв расчет "dgreen"? Компилятор, конечно, не сказал вам этого.

Затем повсюду повторение - forцикл существует столько раз, сколько существует режимов рендеринга, мы продолжаем делать «правый минус левый, разделенный на шаги». Гадкий и подверженный ошибкам. Вы заметили, что я сравниваю, используя «i» в цикле Гуро, когда я должен был использовать «j»? Компилятор опять молчит.

А как насчет if / else / ladder для модов? Что если я добавлю новый режим рендеринга через три недели? Я буду помнить, чтобы обрабатывать новый режим во всем "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;
      }
  }

Теперь посмотри на это. Мы больше не делаем объединение типов супов: у нас есть определенные типы для каждого режима. Они повторно используют свой общий материал (поле «x»), наследуя от базового класса ( CommonPixelData). И шаблон заставляет компилятор CREATE (то есть генерировать код) тремя различными функциями, которые мы написали бы сами в 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. и самое главное: ни одно из того, что мы сделали, не оказывает никакого влияния на время выполнения. Этот код будет работать JUST так же быстро, как и эквивалентный код C - фактически, если код C использовал указатели функций для вызова различных WorkOnPixelверсий, код C ++ будет БЫСТРЕЕ, чем C, потому что компилятор встроит WorkOnPixelспециализацию шаблона конкретного типа. вызов!

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

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

Но это говорит только о том, что ... смотри, с кем ты работаешь. Там нет языка, чтобы оградить вас от некомпетентных пользователей (нет, даже не Java).

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

ttsiodras
источник
18
+1 за "нет, даже не Ява" :)
Натан Осман
53
+1 за пример. Это был длинный пост, но сравнение кода на C и C ++ впечатляет.
paercebal
Вот почему, дамы и господа, существует lex / yacc. По той же причине я никогда не осознавал, что части c ++ попадают в одну и ту же философию генерации кода. Мне придется посмотреть на это снова когда-нибудь.
Спенсер Рэтбун
2
Я написал много кода для 2D-рендеринга (более десяти лет назад) и столкнулся с этой проблемой при переносе с C на C ++: как определить структуру пикселей, если ваша линия сканирования состоит из 1-битных пикселей (8 пикселей в байт)? А когда ваша линия сканирования состоит из байтов R, G и B (3 байта на пиксель)? А когда у вас есть три отдельных буфера для R, G и B? Вы знаете ответ: C ++ там не поможет, и настаивание на использовании шаблонов позволит вам потерять много места и времени на оптимизацию
Уолтер Тросс
Почему вы используете шаблоны в C ++ для этого? Ваш метод объявляет параметр базового класса, поэтому, с моей точки зрения [программиста C #], похоже, что вы можете просто передать экземпляр производного типа в параметр базового типа. Я не знаю C ++, не могли бы вы объяснить, пожалуйста?
Влад
79

RAII для победы ребенка.

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

Motti
источник
20
«C ++: единственный серьезно детерминированный вариант. Спросите своего доктора об этом сегодня».
Кайл Стрэнд,
2
Продолжение: Rust теперь соперник в этой области. Смотрите базовый пример RAII и документацию о методах деструкторов Rust .
Кайл Стрэнд,
1
C будет таким же детерминированным, но требует больше работы, чтобы убедиться, что это действительно происходит при использовании памяти,
выделенной из
1
@Baldrickk в C вы должны писать код очистки везде, где вы используете ресурс. В C ++ вы пишете это один раз , в определении ресурса. И C, и Java страдают от ошибок «ресурс, использованный после удаления» и «утечка ресурсов», потому что очистка не происходит автоматически . Память не единственный ресурс.
Caleth
70

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

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

    Требуется некоторое время, чтобы обернуть вашу голову (у меня ушло пару лет, прежде чем она щелкнула), но когда вы это сделаете, это может сделать жизнь намного проще.

  2. Обработка текста в C ++ на несколько порядков менее болезненна, чем в C.

Джон Боде
источник
35
+1 за обработку текста, о которой я полностью забыл в своем ответе.
Конрад Рудольф
8
Хех, мне было особенно тяжело обрабатывать текст по сравнению с, скажем, Python ..
Нильс
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, я бы сидел в гостиной и смотрел на« Разрушителей легенд » с моей женой, а не сидел в своем офисе в 9 вечера».

Боб Мерфи
источник
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используется для исключения из оптимизации псевдонимов, так как же это поможет ускорить процесс ? а что такое "параметр статического массива"? и как "стиль" влияет на производительность?
underscore_d
1
@underscore_d ограничивает оптимизацию разрешений, основанную на гарантии отсутствия псевдонимов; параметры статического массива позволяют компилятору предполагать, что аргумент указателя не равен NULL и что этот указатель указывает как минимум на заданное количество элементов; Слово «стиль» имеет несколько значений, и если вывести его из контекста, это изменит его значение - я говорю о том, как, например, исключения заставляют использовать умные указатели.
Мартынкунев
1
@martinkunev Хм, поэтому мне интересно, будет ли параметр статического массива включать что-либо функционально отличное от шаблона C ++ с использованием T (&arr)[n]или std::array<T, n>- придется исследовать этот вопрос еще, так как там не так много информации. Это имеет смысл в умных указателях, безусловно, хороший пример. Если кодирование на равных игровых полях, мы не будем использовать исключения, поэтому не будет понесено никаких потенциальных затрат ... однако я подозреваю, что вы могли бы сослаться на то, как, когда сторонние библиотеки входят в картину, много предположений в опасности.
underscore_d
27

Я рассматриваю C ++ как язык 1990-х, язык ушедшей эпохи.

В то время он был большим, потому что предлагал языковые конструкции и механизмы более высокого уровня по более низкой цене с точки зрения производительности. Это был универсальный инструмент для разработки всего, от приложений адресной книги до программного обеспечения авионики, и это вдохновило OO. ООП решило проблему голода и СПИДа, и да, я обвиняю С ++ в том, что в конце 1990-х годов, когда я впервые начал программировать, я пытался «промыть мозги», что любой не-ОО-язык не стоит изучать.

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

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

Благовест Буюклиев
источник
11
Так что не меняйте случайные байты с помощью указателей. Это не так сложно избежать, не так ли?
Дэвид Торнли
11
@Blagovest: я согласен с вами относительно сложности C ++, и я бы никогда не использовал его для замены объектно-ориентированного языка. Но, несмотря на всю сложность, он все равно выигрывает у меня из-за множества преимуществ, изложенных в разных ответах (абстракция, передача ресурсов, обработка строк…). Фактически, вы назвали несколько допустимых областей, где C ++ все еще актуален и где он намного превосходит C.
Конрад Рудольф
6
@Blagovest: Вот почему я держусь подальше от темных углов. В C ++ легче быть ограбленным, чем на любом другом языке, который я знаю. Используя его, я получаю выгоду от RAII, намного лучшую обработку строк, чем C, классы шаблонов типа STL, функции OO и другие преимущества, которые он имеет над C.
Дэвид Торнли
24
@Blagovest: Нет, ты не. Например, того, что вы упомянули, недостаточно для достижения RAII, и у контейнерных классов есть функциональность, которая выходит за рамки простых структур данных, созданных вручную. Если вы думаете, что это возможно, вы никогда не изучали C ++ хорошо.
Дэвид Торнли
5
@Jaroslaw Я не понимаю, почему многоядерные машины могут заглушить ООП. Если вы имеете в виду C ++, я могу видеть, откуда вы пришли. ООП является фундаментальной концепцией во многих современных языках программирования, особенно в языках высокого уровня. Даже C может быть OO, если вы запрограммируете его таким образом. Это просто не так удобно, как C ++ IMO.
vedosity
21

По словам Линуса , нет:

Когда я впервые посмотрел на исходный код Git, мне показалось странным две вещи: 1. Чистый C в отличие от C ++. Понятия не имею почему. Пожалуйста, не говорите о переносимости, это BS.

ВЫ полны ерунды.

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

Другими словами: выбор C - единственный разумный выбор. Я знаю, что Майлз Бэйдер в шутку сказал «разозлить тебя», но на самом деле это правда. Я пришел к выводу , что любой программист , который предпочел бы проект быть в C ++ над C, скорее всего , программист , что я действительно бы предпочел , чтобы разозлить, чтобы он не пришел и ввернуть любой проект , я участвую с участием.

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

  • бесконечное количество боли, когда они не работают (и любой, кто говорит мне, что STL и особенно Boost стабильны и переносимы, настолько полны BS, что это даже не смешно)

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

Другими словами, единственный способ сделать хороший, эффективный и системный и переносимый C ++ в конечном итоге ограничить себя всеми вещами, которые в основном доступны в C. А ограничение вашего проекта на C означает, что люди не будут это делать вверх, а также означает, что вы получаете много программистов, которые действительно понимают проблемы низкого уровня и не облажаются с любой идиотской ерундой "объектной модели".

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

Если вам нужна VCS, написанная на C ++, поиграйте с Monotone. В самом деле. Они используют «настоящую базу данных». Они используют «хорошие объектно-ориентированные библиотеки». Они используют "хорошие абстракции C ++". И, откровенно говоря, в результате всех этих дизайнерских решений, которые звучат так привлекательно для некоторых людей из CS, конечный результат - ужасный и непреодолимый беспорядок.

Но я уверен, что тебе понравится больше, чем мерзавец.

      Linus
Matthieu
источник
62
Я не думаю, что Линус должен быть тем парнем, к которому можно обратиться за спорами. Его нападки ужасно субъективны и незрелы. У него действительно есть несколько хороших моментов, но они настолько глубоко похоронены (ниже «ерунды», как и ерунды), что их очень трудно найти.
Конрад Рудольф
19
Ха-ха, это был хороший смех. Я никогда не хочу встречаться с этим парнем.
Феликс Домбек
30
Линус напоминает мне об очень талантливом кровельщике, который никогда не вешал гипсокартон, но называет парней из гипсокартона анютиными глазками, потому что они используют гвозди вместо шурупов.
Боб Мерфи
8
У Линуса есть пункт, но он выражает его слишком резко, чтобы воспринимать его всерьез.
Благовест Буюклиев
39
Я согласен с @Daniel: если есть кто-то, кто может говорить о расширении границ аппаратного обеспечения, это Джон Кармак, создатель Doom, Quake и других игр и основатель программного обеспечения Id. Несколько месяцев назад он написал это о c и c ++ в твиттере: «IMO, хороший код C ++ лучше, чем хороший код C, но плохой C ++ может быть намного, намного хуже, чем плохой код C». twitter.com/#!/ID_AA_Carmack/status/26560399301
Онема
18

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

РЕДАКТИРОВАТЬ: Есть другие языки, которые хорошо взаимодействуют с C, так что если вам не нравится Python, есть альтернативы.

Ларри Коулман
источник
3
Как насчет встроенной разработки? Python не всегда доступен, и разница в скорости между C и хорошо написанным C ++ незначительна на устройствах после определенного уровня вычислительной мощности. Конечно, я полагаю, что компилятор C ++ тоже не всегда будет доступен ...
Джеймс
6
@James "хорошо написанный C ++" - вот в чем подвох :(
dss539
5
Я согласен с этим ответом, сделайте высокий уровень с python, так как вы напишите его примерно в 3 раза быстрее, профилируете, а затем устраните узкие места, заменив их на C / C ++. Излишне говорить «заменить узкое место кодом C ++», так как вы не будете выполнять высокий уровень с кодом, который вам нужен, чтобы быть быстрым, поскольку это будет код низкого уровня. Есть одна вещь: я не знаю, как связать c ++ с python: /. но с точки зрения времени, потраченного перед экраном и эффективностью, я думаю, что это лучшее решение, так как большая часть кода C ++ будет быстрой ни за что!
Jokoon
8
Работайте в большой финансовой компании и создайте сложную финансовую систему в большой распределенной команде на Python и посмотрите, как вам это понравится. Этот опыт научит вас: а) преимуществам безопасности типов, б) преимуществам компиляторов, сохраняющих ваш приклад, в) СМЕШНОМУ коду, который Python позволяет писать новичкам. Люди говорят, что легко застрелить ногу с помощью C ++ -> некоторые вещи, написанные на Python, могут работать, но могут быть безумием. Прямо сейчас я бы предпочел работать на C ++ ...
MrFox
1
@suslik: Вау, я шокирован тем, что кто-то на самом деле использует python для такой системы. Я согласен с вами по поводу плохого кода noob Python; Я сам видел это.
Ларри Коулман
13

Есть ли причина использовать C ++? Конечно.

Некоторые люди могут просто предпочесть использование C ++ другим параметрам. Спрашивать, есть ли причина использовать C ++, все равно, что спрашивать, почему нам нужно иметь сотни видов мороженого. Не всем нравится просто придерживаться ванили.

Если разработчики уже очень хорошо разбираются в C ++, вопрос для них может заключаться не в том, «зачем его использовать?», А в том, почему? Кажется, сейчас в SO происходит такая модная анти-C ++ вещь, но, верьте или нет, не все подписываются на это. Некоторые люди могут просто любить C ++ лучше, чем другие языки.

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

GrandmasterB
источник
12

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

  • Лучшее управление памятью
  • Более сильная система типов
  • Лучшая стандартная библиотека
  • Пространства имен
  • и т.п.
Оливер Вейлер
источник
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
@ Джордж: Потому что ничего не изменилось, кроме того, что он на два (считай) символов короче? Это не решает никаких проблем, это не выделяет никаких подводных камней, оно даже не делает ничего крутого, например, продлевает время жизни временной переменной (с которой справляются ссылки).
Бен Фойгт
@Ben: Вы что-то забываете - ссылка всегда действительна. Указатели могут указывать на что угодно (включая NULL), что может привести ко всем видам ошибок памяти, если что-то не сделано правильно. Ссылки никогда не могут быть NULL, а адрес, на который они указывают, никогда не может быть изменен.
Натан Осман
5
@ Джордж: «ссылка всегда действительна» - это просто ложь. Я приведу пример, если вам нужен, но я надеюсь, что вы достаточно опытны, чтобы уже знать об этом. И я не говорю о формировании недопустимой ссылки с использованием недопустимого указателя. Для функций, использующих указатели, требуется документация с указанием предварительных условий для аргументов. Но практически все функции нуждаются в таком уровне документации, поэтому нелепо называть это ударом по указателям.
Бен Фойгт
5

Где и почему обычно собираются быть:

  • знакомство
  • желаемые особенности языка
  • конкретные библиотеки, которые вы хотите использовать
  • Требования к производительности

Для программирования на стороне сервера вы часто можете выбирать из множества языков, скомпилированных или интерпретированных. Обычно выбор языка зависит от того, на какой платформе вы или ваша команда будете наиболее эффективны. Или, если у вас еще нет команды, наличие навыков на рынке.

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

оборота диетбудда
источник
2
Знакомство - причина номер 1, и я удивлен, что ты первый, кто об этом упомянул.
Пол Мясник
4

C ++ против Python против Perl не может быть легко судить. Это зависит от проекта и требований.

C ++ имеет арсенал утилит с давних времен, работающих на многих платформах. Но больно начинать ходить по потокам, просто передавая String в Integer и наоборот.

С ++, с другой стороны, ужасно разбирается в зависимости от библиотек. Как только вы что-то скомпилируете в GCC X или VC ++ Y, вы не можете полагаться на то, что код будет выполняться следующей версией этих инструментов. Тот же ад в Windows, такой же ад и в Unix.

Perl берет свою силу из мира Unix, но особенно как инструмент регулярных выражений. Это то, что используется большую часть времени. Наряду с некоторыми довольно серьезными инструментами, которые даже Java не может сделать это обычным способом (посмотрите, как загрузить файл на веб-сервер), Perl «просто делает это».

Python - это простой, гибкий и динамичный язык. Настолько легко, что вы можете отправить целое число в функцию, сценарий ожидает строку, но вы можете получить результат! Неожиданно, но результат. Так что программист должен быть очень осторожен. IDLE предлагает некоторую отладку, но когда вы подключены к системе TELNET или подключены по трем уровням SSH и хотите найти свою проблему, отладчик не будет рядом с вами. Но он может быстро выполнить большую математическую работу.

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, или даже воином, и, возможно, монахом из Хаскелла. Но языки заставляют нас говорить с компьютерами, языки не созданы для того, чтобы мы были компьютерами!

jokoon
источник
2

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

будет говорить
источник
8
Ура, вы использовали ключевое слово «класс». Теперь вы понимаете дизайн ОО!
dss539
Мой C ++ называется C с пространствами имен.
JSZ
6
Мой C ++ называется, хм .. Манодж C ++.
Manoj R
+1 Классы это единственная причина, почему я использую C ++.
МБк
... хорошо, также исключения.
МБк
0

Там на самом деле один ответ на все вопросы, сформированные следующим образом. Лучшая причина использовать технологию X вместо технологии Y (где X и Y находятся примерно на одном уровне [как почти все современные языки программирования]), потому что вы уже знаете X и не знаете Y.

(но после прибытия Хаскелла не было никаких причин использовать что-либо еще)

vegai
источник
0

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

Однако я бы не использовал Python, Perl и т. Д., Чтобы избежать использования C. На самом деле я предпочитаю C #, потому что мне нравится хорошая библиотека (которая является сильной стороной .NET), и мне нравятся статически типизированные языки. Бу хорошая альтернатива. Но на самом деле Haskell , OCaml , D , ML и все в порядке.

Peter Mortensen
источник
7
Вы упустили момент.
Мэтт Джоунер
@ Matt Joiner: я уверен, что нет. Что я пропустил?
Вопрос в том, чтобы не использовать C ++.
Matt Joiner
@Matt Joiner: хм, с другой стороны, я вижу, что меня спрашивают. Но, похоже, я тоже ответил на это (я сказал, что не беспокойтесь и альтернативы, которые я использую)
Я почти хочу понизить это из-за C # ...
Vreality