Ситуации, где “старые” функции C могли бы быть лучше, чем более новые C++? [закрытый]

16
задан PeterK 9 July 2010 в 10:29
поделиться

10 ответов

Вывод в стиле printf () C обычно быстрее, чем вывод ostream C ++. Но, конечно, он не может обрабатывать все типы, которые может выводить C ++. Это единственное преимущество, о котором я знаю - обычно из-за агрессивного встраивания C ++ может быть намного быстрее C.

9
ответ дан 30 November 2019 в 17:14
поделиться

Когда вы пишете C++, пишите C++. Когда вы пишете C, пишите C. Тот, кто говорит иначе, вероятно, не чувствует разницы или считает C++ "лучшим C". Это не так; C++ - это собственный язык со своими особенностями, и в основном он совместим с C с единственной целью облегчения конвертации.

4
ответ дан 30 November 2019 в 17:14
поделиться

Что касается производительности, я раньше был конкурентом USACO. Я быстро обнаружил, что 98% времени выполнения одной из моих программ было потрачено на использование C ++ IOStreams. Переход на fscanf снизил накладные расходы в десять раз. С точки зрения производительности конкурса вообще нет.

4
ответ дан 30 November 2019 в 17:14
поделиться

Я думаю, что стиль C лучше, когда вам нужно управление необработанной памятью. Это немного громоздко делать с конструкциями C ++, и, например, у вас нет realloc ().

Кто-то, кто проголосовал против, вероятно, никогда не пытался исследовать эту тему.


Меня удивляет, как люди не могут представить себя в разных положениях. Я не говорю, что все должны использовать конструкции в стиле C. Я говорю, что стиль C лучше, когда вам НУЖНО необработанное управление памятью. Кто-то должен написать все эти безопасные классы / библиотеки (включая стандартную библиотеку, сборщики мусора, пулы памяти). Ваш опыт, в котором он вам никогда не понадобится, не охватывает всех случаев.


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

3
ответ дан 30 November 2019 в 17:14
поделиться

Где использование возможностей C++ может быть проблематичным:

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

Тем не менее, некоторые/большинство возможностей C++ довольно удобны и полезны, если использовать их с осторожностью. Помните поговорку "С C++ труднее прострелить себе колено, но если вы это сделаете, это будет стоить вам всей ноги".

1
ответ дан 30 November 2019 в 17:14
поделиться

Иногда я предпочитаю указатели и memcpy итераторам и std :: copy , когда мне не нужен общий код.

То же самое и с iostreams, они удобны и расширяемы, но есть много ситуаций, когда [f | s] printf / scanf столь же просты.

0
ответ дан 30 November 2019 в 17:14
поделиться

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

x = y;

В Си это присваивание и только присваивание. Значение y (после возможного преобразования) копируется в x.

В C++ это может буквально означать что угодно.

  • Простое присвоение,
  • определенный пользователем оператор преобразования в y, который удаляет интернет и возвращает значение того же типа, что и x
  • Есть конструктор, который создает объект типа x из y, после расплавления атомной электростанции. Это значение присваивается x.
  • Есть определенный пользователем оператор присваивания, который позволяет присваивать значения из кучи других типов, для которых у y есть оператор преобразования или которые каким-то другим способом можно получить из y. В операторе присваивания есть ошибка, которая может создать черную дыру, потому что он является частью программного обеспечения для работы БАК.
  • больше из вышеперечисленного.

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

9
ответ дан 30 November 2019 в 17:14
поделиться

Я не думаю, что использование функций в стиле printf вместо iostreams оправдано. iostreams просто значительно ускоряют время разработки и отладки, и гораздо меньше подвержены ошибкам (например, вспомните переполнения буфера, неправильные спецификаторы типов %, неправильное количество аргументов ... и самая большая проблема в том, что компилятор вообще не может вам помочь). И если вы не используете endl, когда он не нужен, cout не намного медленнее, чем printf.

Так что, в целом, вы должны использовать C++ iostreams, и только если профилирование показывает, что критические секции занимают слишком много времени из-за вызовов iostream, тогда оптимизируйте эти секции функциями в стиле C, но убедитесь, что используете более безопасные версии функций, например snprintf вместо sprintf.

Примеры:

Допустим, у вас есть переменная int foo, которую вы printf во многих местах, позже, во время разработки, вы понимаете, что вам нужно, чтобы foo было double. Теперь вам придется менять спецификаторы типов в каждом вызове стиля printf, который использует foo. И если вы пропустите хоть одну строчку, добро пожаловать в страну неопределенного поведения.

Недавно у меня был случай, когда моя программа упала из-за того, что я пропустил простую запятую, а из-за великой команды printf-style мой компилятор мне не помог: printf("i will crash %s" /*,*/ "here");. С iostreams такого бы тоже не произошло.

И, конечно, вы не можете расширить поведение printf и friend для работы с вашими собственными классами, как это можно сделать с iostreams.

1
ответ дан 30 November 2019 в 17:14
поделиться

Старый добрый C! Ах, дни до ANSI ... Я определенно скучаю по тому, что практически не было проверки типов аргументов и возвращаемых значений или когда компилятор предполагал, что что-то нетипизированное является int, а не ошибкой.

Серьезно, хотя - есть довольно хороший аргумент против использования исключений для обработки ошибок. Я прочитал довольно достойный аргумент против исключений для работы на системном уровне, и в основном я думаю, что проблема в том, что вы не можете просто прочитать блок кода и знать, что он не будет бросать в C ++, тогда как вы можете читать большинство C и говорят «все ошибки (на этом уровне) перехватываются» или «те, которые не имеют значения, не имеют значения».

1
ответ дан 30 November 2019 в 17:14
поделиться

Я не мог дать вам окончательного ответа; однако я нашел это довольно устаревшее сравнение интересным.

http://unthought.net/c++/c_vs_c++.html

1
ответ дан 30 November 2019 в 17:14
поделиться