Какие гарантии существуют при чередовании чтения и записи?
При работе с С++ 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;
читается из сети. Я не уверен, что это поведение согласуется с общим контрактом на потоки. Если бы я должен был догадаться, возможно, имеет место один из следующих трех:
- Контракт
iostream
ничего не говорит о чередовании чтения и записи или
- В общем случае контракт
iostream
ничего не говорит о чередовании чтений и записей, но в спецификации, как стандартные типы, такие как fstream
и stringstream
, работают специальные предписания, или
- Контракт
iostream
говорит что-то о чередующихся чтениях и записи, что нарушает класс сетевого потока.
У меня есть копия спецификации, но секция по потокам настолько плотная и загадочная, что ее невозможно, но невозможно. Если бы кто-то мог прояснить, как именно iostream
должен вести себя, когда вы смешиваете чтения и записи, я бы очень признателен.
Ответы
Ответ 1
Я не уверен в главе и стихе стандарта С++ (которого у меня нет, чтобы проверить), но я очень хорошо знаком с C стандарт по этому вопросу (который у меня есть).
C99 заявляет, что поток можно открыть в режиме чтения, записи или обновления. Только последний режим позволяет как чтение, так и запись в один поток, но (цитата):
... вывод не должен сопровождаться вводом без промежуточный вызов функции fflush
или функции позиционирования файла (fseek
, fsetpos
, или rewind
), и вход не должен сопровождаться выходом без промежуточный вызов функции позиционирования файла, если только операция ввода не встречается конец файл.
Я бы предположил, что стандарт С++ говорит что-то подобное где-то: вы должны сбросить или переместить поток до "реверсирования" в направлении чтения/записи.
Изменить: На самом деле есть два отдельных указателя, которые можно запросить с помощью basic_istream::tellg
и basic_ostream::tellp
. Однако я нашел упоминание о возможности того, что два не указывают на одно и то же положение в потоке только в связи с stringstream
, а не на fstream
. Взятый вместе с вышеприведенным утверждением, это имеет смысл именно так. Все еще не могу указать на главу и стих стандарта, хотя, извините.