Вывод в стиле printf () C обычно быстрее, чем вывод ostream C ++. Но, конечно, он не может обрабатывать все типы, которые может выводить C ++. Это единственное преимущество, о котором я знаю - обычно из-за агрессивного встраивания C ++ может быть намного быстрее C.
Когда вы пишете C++, пишите C++. Когда вы пишете C, пишите C. Тот, кто говорит иначе, вероятно, не чувствует разницы или считает C++ "лучшим C". Это не так; C++ - это собственный язык со своими особенностями, и в основном он совместим с C с единственной целью облегчения конвертации.
Что касается производительности, я раньше был конкурентом USACO. Я быстро обнаружил, что 98% времени выполнения одной из моих программ было потрачено на использование C ++ IOStreams. Переход на fscanf снизил накладные расходы в десять раз. С точки зрения производительности конкурса вообще нет.
Я думаю, что стиль C лучше, когда вам нужно управление необработанной памятью. Это немного громоздко делать с конструкциями C ++, и, например, у вас нет realloc ().
Кто-то, кто проголосовал против, вероятно, никогда не пытался исследовать эту тему.
Меня удивляет, как люди не могут представить себя в разных положениях. Я не говорю, что все должны использовать конструкции в стиле C. Я говорю, что стиль C лучше, когда вам НУЖНО необработанное управление памятью. Кто-то должен написать все эти безопасные классы / библиотеки (включая стандартную библиотеку, сборщики мусора, пулы памяти). Ваш опыт, в котором он вам никогда не понадобится, не охватывает всех случаев.
Другая ситуация - когда вы пишете библиотеку. С помощью C вы получите красивую таблицу символов, которую можно легко связать со многими другими языками программирования. С C ++ у вас будет name mangling , что затрудняет (но не делает невозможным) использование библиотеки в среде, отличной от C ++.
Где использование возможностей C++ может быть проблематичным:
Тем не менее, некоторые/большинство возможностей C++ довольно удобны и полезны, если использовать их с осторожностью. Помните поговорку "С C++ труднее прострелить себе колено, но если вы это сделаете, это будет стоить вам всей ноги".
Иногда я предпочитаю указатели и memcpy
итераторам и std :: copy
, когда мне не нужен общий код.
То же самое и с iostreams, они удобны и расширяемы, но есть много ситуаций, когда [f | s] printf / scanf столь же просты.
Есть одна вещь, на которую иногда указывают программисты на C, и которую стоит принять во внимание: Если держаться подальше от макросов, то в основном очевидно, что делает строка кода на Си. Возьмем, к примеру, следующее:
x = y;
В Си это присваивание и только присваивание. Значение y (после возможного преобразования) копируется в x.
В C++ это может буквально означать что угодно.
Чтобы сделать это еще более интересным, каждая операция может выбросить исключение в C++, что означает, что каждая строка должна быть написана так, чтобы можно было откатить то, что она изменила, что иногда трудно, когда вы не можете сказать, что строка на самом деле делает. И что еще хуже, ваша программа может мгновенно завершиться, потому что исключение произойдет из-за того, что присваивание вызывается во время разворачивания исключения. В C++ все имеет тенденцию становиться "вертикально сложным", что предъявляет свои требования к возможностям и коммуникативным навыкам разработчиков.
Я не думаю, что использование функций в стиле 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.
Старый добрый C! Ах, дни до ANSI ...
Серьезно, хотя - есть довольно хороший аргумент против использования исключений для обработки ошибок. Я прочитал довольно достойный аргумент против исключений для работы на системном уровне, и в основном я думаю, что проблема в том, что вы не можете просто прочитать блок кода и знать, что он не будет бросать в C ++, тогда как вы можете читать большинство C и говорят «все ошибки (на этом уровне) перехватываются» или «те, которые не имеют значения, не имеют значения».
Я не мог дать вам окончательного ответа; однако я нашел это довольно устаревшее сравнение интересным.