Подтвердить что ты не робот

С++ Streams против C-style IO?

Я программировал некоторый С++ для небольшого проекта хобби, когда заметил, что я использую операции типа C для доступа к IO (printf, fopen и т.д.).

Считается ли "плохой практикой" задействовать функции C в проектах на С++? В чем преимущества использования потоков по доступу IO C-стиля?

4b9b3361

Ответ 1

Это горячая тема.

Некоторые люди предпочитают использовать С++ IO, поскольку они безопасны по типу (у вас не может быть расхождения между типом объекта и типом, указанным в строке формата) и более естественно протекать с остальной частью С++ способ кодирования.

Однако есть также аргументы для функций C IO (мои личные фавориты). Некоторые из них:

  • Они легче интегрируются с локализацией, так как вся строка для локализации не разбивается на меньшие строки, а с некоторой реализацией локализатор может изменить порядок введенного значения, переместить их в строку,...
  • Вы можете непосредственно увидеть формат текста, который будет написан (это может быть очень сложно с потоковыми операторами).
  • Поскольку нет вставки и только один экземпляр функции printf, сгенерированный код меньше (это может быть важно во встроенной среде).
  • Быстрее, чем функция С++ в некоторой реализации.

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


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


Изменить: добавление некоторой информации о преимуществах семейства функций форматирования printf, относящихся к локализации. Обратите внимание, что эта информация действительна только для некоторой реализации.

Вы можете использовать %m$ вместо %, чтобы ссылаться на параметр по индексу, а не ссылаться на них последовательно. Это можно использовать для изменения порядка в форматированной строке. Следующая программа напишет Hello World! на стандартный вывод.

#include <stdio.h>
int main() {
    printf("%2$s %1$s\n", "World!", "Hello");
    return 0;
}

Рассмотрим перевод этого кода на С++:

if (nb_files_deleted == 1)
    stream << "One file ";
else
    stream << nb_file_deleted << " files ";
stream << removed from directory \"" << directory << "\"\n";

Это может быть очень сложно. С printf (и библиотекой типа gettext для обработки локализации) код не смешивается со строкой. Таким образом, мы можем передать строку команде локализации и не будем обновлять код, если на каком-либо языке есть специальный случай (на некотором языке, если количество объектов равно 0, вы используете множественную форму на другом языке, существует три формы для сингулярных, одна, когда есть два объекта и множественная форма,...).

printf (ngettext ("One file removed from directory \"%2$s\"",
                  "%1$d files removed from directory \"%2$s\"",
                  n),
        n, dir);

Ответ 2

printf и друзья ужасно опасны по сравнению с <iostream> и не могут быть расширены, плюс, конечно, fopen, а друзья не имеют RAII, а это означает, что, если вы не доказали с профилировщиком, что вам определенно нужно (что вы доказали, что существует на вашей платформе и в вашем коде), вам нужно быть идиотом до printf.

Изменить: Локализация - это интересная вещь, которую я не рассматривал. Я никогда не локализовал какой-либо код и не могу прокомментировать относительную локализационную способность printf и <iostream>

Ответ 3

Для небольшого проекта для хобби я, вероятно, поеду с более безопасными потоками С++ io.

Забавно, я никогда не видел нетривиального реального проекта, который использует любой из них. Во всех случаях мы использовали некоторые абстракции, построенные поверх родного OS API для ввода-вывода.

Ответ 4

Ничто не может считаться плохой практикой, если оно имеет определенную цель. Я имею в виду, что если IO является узким местом в программе, то да, IO C-style работает быстрее, чем С++ IO. Но если это не так, я бы пошел с потоком С++ stream. Cuz это cuter:)

Ответ 5

<сильные > Преимущества

  • Тип безопасности: типы аргументов потоковых операций С++ проверяются во время компиляции, а аргументы printf передаются через ..., вызывая поведение undefined, если они не соответствуют форматированию.
  • Управление ресурсами: объекты потока С++ имеют деструкторы для закрытия дескрипторов файлов, свободных буферов и того, что у вас есть. C потоки требуют, чтобы вы не забыли позвонить fclose.

Недостатки

  • Производительность: это, конечно, зависит от реализации, но я нашел форматирование с потоками С++ значительно медленнее, чем эквивалентное форматирование printf.

Ответ 6

Для этого вам не нужно сначала преобразовывать объекты С++ (особенно string s) в C-совместимые формы.

Ответ 7

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

Ответ 8

Считается ли это "плохой практикой" задействовать функции C в проектах на С++?

Обычно файл IO-кода должен быть инкапсулирован в реализацию класса или функции. Я бы не считал, что любые варианты, которые вы делаете в инкапсулированных реализациях, являются "плохой практикой", я резервирую этот термин для того, что влияет на пользователя вашей библиотеки или кода (т.е. Интерфейса). Если вы подвергаете свой файловый механизм ввода-вывода в интерфейсе, то IMO, это плохо, если вы используете IO-поток или функции ввода-вывода C-стиля.

Я бы сказал, что функции IO C-стиля (вероятно, всегда) - худший выбор.

В чем преимущества использования потоков по доступу IO C-стиля?

Во-первых, они лучше интегрируются со стандартными конструкциями С++, такими как std::string. Они довольно хорошо интегрируются с STL <algorithms>. И они позволяют создавать инкапсулированные пользовательские операторы чтения/записи (< < и → ), так что ваши пользовательские классы почти выглядят как примитивные типы, когда дело доходит до операций ввода-вывода.

Наконец, потоки ввода-вывода на С++ могут использовать механизм исключения для сообщения об ошибках в потоке или операции чтения/записи. Они делают код IO файла намного приятнее, избегая ужасного вида механизмов кода ошибки (последовательность if-операторов и уродливых while-loops, которые проверяют код ошибки после каждой операции).

Ответ 9

Как правило, вы должны предпочесть операторы С++, они:

- безопасный тип. Вы не рискуете пройти двойной, где формат   вызывает int.

- Расширяемость. Вы можете написать свои собственные вставки и   экстракторы и использовать их.

- Расширяемость. Вы можете определить свои собственные манипуляторы (с помощью   конкретный логический смысл приложения) и использовать их. если ты   хотите изменить формат всего WidgitNumber   (внутренне, int) в вашем выходе, вы меняете   манипулятор; вам не нужно искать весь формат   где% d - WidgitNumber.

- Расширяемость. Вы можете написать свои собственные раковины и источники, и   они могут пересылаться другим стокам и источникам, фильтровать или   расширяя вход или выход по желанию.

(FWIW: Я не думаю, что когда-либо писал приложение, которое не использовал пользовательские → и < операторы, пользовательские манипуляторы и пользовательский streambuf.)

Ответ 10

Считается ли "плохой практикой" задействовать функции C в проектах на С++?

Нет. Функции C часто используются в проектах на С++. Что касается потоков, Руководство по стилю Google С++, например, рекомендуется использовать их только в ограниченных случаях, таких как "ad-hoc, local, human- читаемые и ориентированные на других разработчиков, а не на конечных пользователей".

Каковы преимущества использования потоков по доступу IO C-стиля?

Основными преимуществами являются безопасность и расширяемость типов. Однако потоки С++ имеют серьезные недостатки, см. ответы на этот вопрос, такие как проблемы с локализацией, плохой отчетностью об ошибках, раздувание кода и проблемы с производительностью в некоторых реализациях.