Странно поведение на поток от низове, предаван по референция

За проект бих искал да използвам 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?

И защо не мога да предам поток от низове по стойност?


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
Очаквах operator‹‹ да е дефиниран за 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