Какие гарантии существуют для чередующихся операций чтения и записи? - PullRequest
11 голосов
/ 14 февраля 2011

При работе с C ++ std::iostream (например, std::fstream или std::stringstream, гарантирует ли стандарт что-либо об отношениях между операциями чтения и записи, выполняемыми в одном потоке? То есть, действительно ли это так, что если Я записываю данные в std::fstream, затем пытаюсь прочитать данные из этого потока, я должен увидеть данные, которые я написал? Как насчет std::stringstream? В качестве примера, гарантированно ли это работает?

std::stringstream myStream;
myStream << "137 Hello 2.71828";

int myInt;
std::string myString;
double myDouble;

myStream >> myInt >> myString >> myDouble; // Parse as expected?

Или как насчет этого дела?

std::fstream myStream("some-file.txt", ios::in | ios::out);
myStream << "137 Hello 2.71828";

int myInt;
std::string myString;
double myDouble;

myStream >> myInt >> myString >> myDouble; // Parse as expected?

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

myNetworkStream << "Hi there!" << endl;

пишет по сети, а

myNetworkStream >> myValue;

читает из сети. Я не уверен, что такое поведение согласуется с общим контрактом для потоков. Если бы мне пришлось угадывать, вероятно, справедливо одно из следующих трех:

  1. В договоре iostream ничего не говорится о чередующемся чтении и записи, или
  2. Как правило, в контракте iostream ничего не говорится о чередующемся чтении и записи, но в спецификации есть определенные предвидения, регулирующие работу стандартных типов, таких как fstream и stringstream, или
  3. В контракте iostream действительно говорится что-то о чередующемся чтении и записи, что делает мой сетевой поток нарушающим класс.

У меня есть копия спецификации, но раздел о потоках настолько плотный и загадочный, что его почти невозможно проследить. Если бы кто-нибудь мог уточнить, как именно iostream должен вести себя, когда вы смешиваете чтение и запись, я был бы очень признателен.

1 Ответ

10 голосов
/ 14 февраля 2011

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

C99 утверждает, что поток может быть открыт в режиме чтения, записи или обновления. Только последний режим позволяет и чтение, и запись в один и тот же поток, но (цитата):

... вывод не должен сопровождаться непосредственно вводом без промежуточный вызов функции fflush или функции позиционирования файла (fseek, fsetpos, или rewind), и за входом не должно следовать непосредственно выход без промежуточный вызов функции позиционирования файла, если только операция ввода не встречает конец-файл.

Я бы предположил, что в стандарте C ++ где-то сказано что-то похожее: вы должны очистить или изменить положение потока перед тем, как «повернуть» направление чтения / записи.

Редактировать: На самом деле есть два отдельных указателя, которые можно запросить с помощью basic_istream::tellg и basic_ostream::tellp. Однако я обнаружил, что два не могут указывать на одну и ту же позицию в потоке только в связи с stringstream, а не для fstream. Взятый вместе с вышеупомянутым утверждением, это имеет смысл таким образом. Тем не менее, не могу указать вам главу и стих стандарта, извините.

...