Вопрос

На самом деле это не вопрос дизайна, хотя может показаться, что так оно и есть.(Ну, ладно, это своего рода вопрос дизайна).Что мне интересно, так это почему C ++ 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();
}

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

Это было полезно?

Решение

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

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

Причина в том, что это вызовет цикл преобразования, который, в свою очередь, может привести к проблемам.Например, предположим, что std::string был бы конвертирован в строку C, чтобы вы могли использовать std::stringы с fstreams.Предположим также, что строка 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().

Другие советы

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

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

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

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

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

Так что, когда это будет доработано и реализовано, вам это больше не поможет :)

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

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

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top