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

Почему классы std:: fstream не принимают std::string?

Это не вопрос дизайна, действительно, хотя это может показаться. (Ну, ладно, это вопрос дизайна). Мне интересно, почему классы С++ std::fstream не принимают std::string в своих конструкторах или открытых методах. Все любят примеры кода, поэтому:

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::string filename = "testfile";      
    std::ifstream fin;

    fin.open(filename.c_str()); // Works just fine.
    fin.close();

    //fin.open(filename); // Error: no such method.
    //fin.close();
}

Это позволяет мне постоянно работать с файлами. Разумеется, библиотека С++ использовала бы std::string, где возможно?

4b9b3361

Ответ 1

Приняв строку C, класс С++ 03 std::fstream уменьшил зависимость от класса std::string. Однако в С++ 11 класс std::fstream позволяет передавать std::string для своего параметра конструктора.

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

Причина в том, что это вызовет цикл конверсии, который, в свою очередь, может привести к проблемам. Например, предположим, что std::string будет конвертируемым в строку C, чтобы вы могли использовать std::string с fstream s. Предположим также, что строка C преобразуется в std::string, как и состояние в текущем стандарте. Теперь рассмотрим следующее:

void f(std::string str1, std::string str2);
void f(char* cstr1, char* cstr2);

void g()
{
    char* cstr = "abc";
    std::string str = "def";
    f(cstr, str);  // ERROR:  ambiguous
}

Поскольку вы можете конвертировать любой из двух строк std::string и строки C, вызов f() может разрешить любую из двух альтернатив f() и, следовательно, является неоднозначным. Решение состоит в том, чтобы разбить цикл преобразования, сделав одно направление преобразования явным, и это то, что STL выбрала для c_str().

Ответ 2

Есть несколько мест, где стандартный комитет С++ действительно не оптимизировал взаимодействие между объектами в стандартной библиотеке.

std::string и его использование в библиотеке является одним из них.

Еще один пример: std::swap. Многие контейнеры имеют функцию подкачки, но перегрузка std:: swap не предоставляется. То же самое касается std::sort.

Я надеюсь, что все эти мелочи будут исправлены в предстоящем стандарте.

Ответ 3

Возможно, это утешение: все fstream получили открытый (string const &,...) рядом с открытым (char const *,...) в рабочем черновике стандарта С++ 0x, (см., например, 27.8.1.6 для объявления basic_ifstream)

Итак, когда он будет завершен и реализован, он больше не получит вас:)

Ответ 4

Библиотека потока IO была добавлена ​​в стандартную библиотеку С++ до STL. Чтобы не нарушать обратную совместимость, было принято решение не модифицировать библиотеку ввода-вывода при добавлении STL, даже если это означало некоторые проблемы, подобные тем, которые вы поднимаете.

Ответ 5

@Бернард:
Монолиты "Unstrung". "Все для одного и для всех" могут работать для мушкетеров, но это не так хорошо работает для классных дизайнеров. Вот пример, который не является вполне образцовым, и это иллюстрирует, насколько сильно вы можете ошибиться, когда дизайн превращается в overdesign. Пример, к сожалению, взят из стандартной библиотеки рядом с вами... ~ http://www.gotw.ca/gotw/084.htm

Ответ 6

Это несущественно, это правда. Что вы подразумеваете под большим интерфейсом std::string? Что означает большое значение, в этом контексте - много вызовов методов? Я не шучу, мне действительно интересно.

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

Реальная проблема, я думаю, состоит в том, что библиотека С++ имеет три части; у него есть старая библиотека C, у нее есть STL, и у нее есть строки и iostreams. Несмотря на то, что были предприняты некоторые усилия для объединения различных частей (например, добавление перегрузок в библиотеку C, поскольку С++ поддерживает перегрузку, добавление итераторов в basic_string, добавление адаптеров итератора iostream), существует много несоответствий, когда вы посмотрите на детали.

Например, basic_string включает методы, которые являются ненужными дубликатами стандартных алгоритмов; различные методы поиска, возможно, можно было бы безопасно удалить. Другой пример: локали используют вместо указателей исходные указатели.

Ответ 7

С++ вырос на более мелких машинах, чем монстры, которые мы пишем сегодня на сегодня. Назад, когда iostream был новым, многие разработчики действительно заботились о размере кода (они должны были вместить всю свою программу и данные в несколько сотен КБ). Поэтому многие не хотели втягивать "большую" библиотеку строк С++. Многие даже не использовали библиотеку iostream по тем же причинам, размер кода.

У нас не было тысяч мегабайт оперативной памяти, чтобы выбраться так же, как сегодня. У нас обычно не было связей уровня функции, поэтому мы были во власти разработчика библиотеки, чтобы использовать множество отдельных объектных файлов или тянуть тонны невостребованного кода. Все это FUD заставило разработчиков уклоняться от std::string.

В то время я тоже избегал std::string. "Слишком раздутый", "слишком часто называемый malloc" и т.д. Глупо использовать стековые буферы для строк, а затем добавлять все виды утомительного кода, чтобы убедиться, что он не переполняется.

Ответ 8

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

Ответ 9

Я считаю, что об этом думали и делали, чтобы избежать зависимости; то есть #include <fstream> не следует принуждать к #include <string> .

Честно говоря, это кажется совершенно несущественной проблемой. Лучший вопрос: почему интерфейс std::string настолько большой?

Ответ 10

В настоящее время вы можете легко решить эту проблему: добавьте -std=c++11 к вашему CFLAGS.