Дизайн класса std::ifstream

Те из нас, кто видел красоту STL, стараются использовать ее как можно чаще, а также призывают других использовать ее везде, где мы их видим, используя необработанные указатели и массивы. Скотт Мейерс написал целую книгу по STL под названием Эффективный STL. Но что случилось с разработчиками ifstream, что они предпочли char* std::string. Интересно, почему первый параметр ifstream::open() имеет тип const char*, а не const std::string &. Пожалуйста, взгляните на его подпись:

void open(const char * filename, ios_base::openmode mode = ios_base::in );

Почему это? Почему бы и нет:

void open(const string & filename, ios_base::openmode mode = ios_base::in );

Это серьезная ошибка в дизайне? Или этот дизайн преднамеренный? Что может быть причиной? Я не вижу причин, по которым они предпочли char* std::string. Обратите внимание, что мы все еще можем передать char* последней функции, которая принимает std::string. Это не проблема!

Кстати, я знаю, что ifstream — это typedef, так что без комментариев по поводу моего заголовка.:P. Он выглядит коротким, поэтому я использовал его.

Фактический шаблон класса:

template<class _Elem,class _Traits> class basic_ifstream;

person Nawaz    schedule 09.01.2011    source источник
comment
Единственное, что объединяет потоки с STL, это то, что оба являются частью стандартной библиотеки. Стандартная библиотека != STL.   -  person sbi    schedule 09.01.2011


Ответы (3)


Моя копия стандарта не соответствует ты. Он говорит, что это перегрузки:

void open(const char* s, ios_base::openmode mode = ios_base::in);
void open(const string& s, ios_base::openmode mode = ios_base::in);

Однако эта копия стандарта является черновиком следующей версии стандарта C++0x.

Причина этого в том, что библиотека iostreams предшествует std::basic_string, а также потому, что разработчики библиотеки не хотели, чтобы кому-то приходилось #include <string> и весь связанный с ней багаж, если они не хотят ее использовать.

person Billy ONeal    schedule 09.01.2011
comment
Вероятно, вы смотрите черновик C++0X. - person AProgrammer; 09.01.2011
comment
@AProgrammer: Хм... не знал, что это изменилось. Добавил ссылку на копию, которую я использую, чтобы было понятнее. - person Billy ONeal; 09.01.2011
comment
@Billy ONeal: это не C++03. Я говорю о С++03. - person Nawaz; 09.01.2011
comment
@Nawaz: Хорошо, это разумно. Вторая часть моего ответа по-прежнему верна. Я добавил примечание, что стандартная копия, которая у меня есть, является черновиком. - person Billy ONeal; 09.01.2011
comment
@Billy: Точно так же, как у C++0x есть версия, которая принимает std::string, C++03 мог бы сделать то же самое. Нет? - person Nawaz; 09.01.2011
comment
@Nawaz: Да, могли. Они также могли бы поместить всю стандартную библиотеку в #include <whole_standard_library>, но не сделали этого. - person Billy ONeal; 09.01.2011

Потому что IOStream был разработан задолго до того, как часть STL была интегрирована в стандартную библиотеку. И после этого был создан класс string. Это было довольно поздно в процессе стандартизации, и изменение IOStream не считалось спасением.

Кстати, в рамках незначительных, но удобных изменений в C++0X была устранена подобная проблематика.

person AProgrammer    schedule 09.01.2011

Как правило, получить строку C из std::string не дороже, чем построить std::string из строки C, поэтому, учитывая, что вы, вероятно, захотите использовать std::ifstream с именами файлов, полученными из обоих, использование const char* в интерфейсе не значительные затраты.

Это серьезная ошибка в дизайне?

Что вы не можете сделать с текущим интерфейсом? Какую конкретную и значительную выгоду принесет const std::string& в интерфейсе?

Настоящая польза перегрузки std::string, как мне кажется, заключается в том, что она помогает новичкам, облегчая правильное понимание вещей при первой попытке использовать std::string и потоки вместе. Для опытных разработчиков C++ тривиальные затраты на написание .c_str(), когда это необходимо, скорее всего, будут незначительными по сравнению с остальными усилиями, затраченными на разработку кода.

person CB Bailey    schedule 09.01.2011
comment
@Charles Bailey: это похоже на рационализацию постфактум. :П - person Nawaz; 09.01.2011
comment
@Nawaz: О чем вы просите, если не о рационализации постфактум (учитывая, что текущий интерфейс уже стандартизирован)? - person CB Bailey; 09.01.2011
comment
@Charles Bailey: Я имею в виду, если бы они предпочли std::string char*, вы бы сказали то же самое. Только в обратном порядке. И это все равно выглядело бы рационально.:|... тогда как мой вопрос был о том, почему они сами не использовали std::string, если в этом нет никакого вреда. - person Nawaz; 09.01.2011
comment
В большинстве реализаций строк STL их внутренний буфер все время завершается нулем, поэтому c_str() — это быстрая операция, которая просто возвращает указатель буфера. - person bdonlan; 09.01.2011
comment
@bdonlan: да, но file.open("my very long file name path.txt") вызывает конструкцию std::string, которая включает выделение кучи. - person Yakov Galka; 09.01.2011
comment
Иными словами, если бы я сейчас разрабатывал интерфейс, в котором в качестве входных данных требовалась строка (не произвольные char данные), и эта строка могла бы исходить из строкового литерала, статически выделяемого или динамически вводимого, я обычно выбирал бы const char* вместо const std::string& и не стал бы заморачиваться с перегрузкой. Я не думаю, что плохой дизайн иметь const char* в интерфейсе, я считаю, что это немного более гибко, чем требование std::string, так как использование const shared_ptr<X>& менее гибко, чем const X&; это не навязывает конкретную стратегию хранения. - person CB Bailey; 09.01.2011