Странное поведение строкового потока, переданного по ссылке

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

Код :

#include <iostream>
#include <sstream>

void doStuff(const std::iostream& msg)
{
    std::cerr << msg << std::endl;
}

int main(void)
{
    doStuff(std::stringstream("av"));
}

Вывод: 0xbff4eb40

Может кто-нибудь объяснить, почему я получаю адрес при передаче rvalue?

И почему я не могу передать stringstream по значению?


person BenjaminB    schedule 11.03.2012    source источник


Ответы (2)


Вероятно, вы хотите получить доступ к строке, в которой строковый поток хранит свои данные:

void doStuff(const std::stringstream& msg)
{
    std::cerr << msg.str() << std::endl;
}

Что происходит в вашем коде, так это то, что iostreams содержит void* operator, который возвращает 0, если поток содержит какую-либо ошибку или достиг EOF, и другое значение в противном случае. Это полезно для проверки ошибок.

Когда вы пытаетесь записать свой поток в std::cerr, компилятор понимает, что поток может быть преобразован в void* с помощью этого оператора, и что void* может быть записан в ostream (оператор‹‹ был определен), и, следовательно, использует его.

Обратите внимание, что я изменил сигнатуру метода, чтобы он получал std::stringstream в качестве аргумента, поскольку std::iostream::str не определен (этот метод доступен только для строковых потоков).

person mfontanini    schedule 11.03.2012
comment
Я ожидал, что оператор ‹‹ будет определен для ostreams. - person BenjaminB; 12.03.2012

Вы получаете адрес, потому что он (как и другие потоки) имеет преобразование в void * (что в первую очередь полезно в качестве логического значения, чтобы увидеть, не произошло ли чтение/запись потока).

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

Чтобы распечатать содержимое потока, вы можете сделать что-то вроде:

void dostuff(std::iostream &msg) { 
    std::cerr << msg.rdbuf() << "\n";
}

Изменить: Вот полная демонстрационная программа:

#include <iostream>
#include <sstream>

void show(std::ostream &os) { 
    std::cout << os.rdbuf() << "\n";
}


int main(){ 
    std::stringstream test("whatever");
    show(test);
    return 0;
}

Когда я его выполняю, результат, который я получаю, является ожидаемым «независимо».

person Jerry Coffin    schedule 11.03.2012
comment
iostream::str не существует, тип этого параметра следует изменить на stringstream. - person mfontanini; 12.03.2012
comment
@fontanini: Спасибо - исправлено (хотя и немного по-другому, так, как это справедливо для потоков в целом). - person Jerry Coffin; 12.03.2012