Re: correct usage of ostringstream
On Wed, 25 Jul 2007 09:03:32 -0700, mzdude <jsanga@cox.net> wrote:
The two functions foo() and bar() are trying to do the same thing. foo
doesn't work but bar does. My question "Is bar a leagal function or is
it treading into the undefined behaviour and I'm simply getting away
with it"? I have tried the code both in VC 6 and VC 2005. Both exhibit
the same behaviour.
As long as I use the ostringstream::str() function as the first output
variable it seems to work. As soon as it appears in a different
location, the code will crash.
#include "stdafx.h"
#include <string>
#include <sstream>
using namespace std;
std::string SomeFunc( const std::string &str )
{
// Iterate through string and calculate a checksum
return " checksum ";
}
void foo()
{
const char stx = '\2';
const char etx = '\3';
std::ostringstream os;
os << stx
<< "One"
<< SomeFunc(os.str().substr(1)) // crashes here
<< etx;
std::string done = os.str();
}
In the most tenuous sense, it's well-defined, but the output is unspecified
due to the many possible orders in which the arguments can be evaluated.
You have to realize that the substr expression could be evaluated before
"os << stx" is executed, and if this is done in foo(), it will cause substr
to throw an exception.
void bar()
{
const char stx = '\2';
const char etx = '\3';
std::ostringstream os;
os << stx
<< "One";
os << SomeFunc(os.str().substr(1)) // works but why?
<< etx;
std::string done = os.str();
}
This works because os definitely contains data when you call substr, and
the output is what you expect because the evaluation of etx can't affect
os.str() even if evaluated before that argument. I'd still rewrite it like
this:
os << ...
std::string s = os.str().substr(1);
os << ...
int main(int argc, char * argv[])
{
argc; argv;
Just write "int main()".
foo(); // doesn't work
bar(); // works fine
return 0;
}
Wrapping foo like this may shed some light on the problem:
try
{
foo();
}
catch(std::exception& ex)
{
std::cout << ex.what() << '\n';
}
--
Doug Harrison
Visual C++ MVP