14

I came across a subtle bug a couple of days ago where the code looked something like this:

ostringstream ss;
int anInt( 7 );

ss << anInt << "HABITS";
ss << ends;
string theWholeLot = ss.str();

The problem was that the ends was sticking a '\0' into the ostringstream so theWholeLot actually looked like "7HABITS\0" (i.e. a null at the end)

Now this hadn't shown up because theWholeLot was then being used to take the const char * portion using string::c_str() That meant that the null was masked as it became just a delimiter. However, when this changed to use strings throughout, the null suddenly meant something and comparisons such as:

if ( theWholeLot == "7HABITS" )

would fail. This got me thinking: Presumably the reason for ends is a throwback to the days of ostrstream when the stream was not normally terminated with a null and had to be so that str() (which then cast out not a string but a char *) would work correctly.

However, now that it's not possible to cast out a char * from a ostringstream, using ends is not only superfluous, but potentially dangerous and I'm considering removing them all from my clients code.

Can anyone see an obvious reason to use ends in a std::string only environment?

durron597
  • 31,968
  • 17
  • 99
  • 158
Component 10
  • 10,247
  • 7
  • 47
  • 64
  • My only quibble would be what's a std::string only environment? Any non-trivial program is going to char* system call arguments, etc. That said, there are half a dozen other ways to deal with that and ends has negligible usefulness. – Duck Feb 26 '10 at 00:31
  • Here is some use of `std::ends`: http://stackoverflow.com/questions/624260/how-to-reuse-an-ostringstream/624291#624291 – Johannes Schaub - litb Feb 26 '10 at 03:11
  • 1
    It's not only for strings. It's useful for general streams. Some unix tools need null bytes as terminators. `cout << ends;` will provide them. – Johannes Schaub - litb Feb 26 '10 at 03:17
  • OK. I guess my point is really that if you have an ostringstream you can get a std::string (but not a null terminated c-string) and if you have a std::string then you can get a null terminated c-string. In other words its actually quite difficult through this route to end up with a string that *isn't* null terminated, but you can end up inadvertently with an unnecessary, unwanted and difficult to detect null ins std::string. – Component 10 Feb 27 '10 at 08:24
  • Thanks for the link Johannes, you're quite right about APIs etc that need nulls in data etc. I think if I was creating such a string I might be tempted to insert the null directly (i.e. '\0' rather than ends) since although they both do the same thing, '\0' does not directly imply an end as such. – Component 10 Feb 27 '10 at 08:25

2 Answers2

7

You've essentially answered your own question is as much detail that's needed. I certainly can't think of any reason to use std::ends when std::string and std::stringstream handle all that for you.

So, to answer your question explicitly, no, there is no reason to use std::ends in a std::string only environment.

Peter Alexander
  • 53,344
  • 14
  • 119
  • 168
  • I would say there is no reason to use `std::ends` period. I would say I'm a very experienced C++ programmer and yet I didn't even know it existed. – Andreas Bonini Feb 26 '10 at 00:15
  • 4
    @Andreas, for having just heard about it the first time, you sound extraordinary sure about it :) – Johannes Schaub - litb Feb 26 '10 at 03:13
  • 1
    As Johannes pointed out there are sufficient reasons. Many UNIX programs require the common '\0' terminator, e.g. to pipe text with ASCII characters <= 32 into other programs. I cannot even imagine a life without `find -print0`, `xargs --null` or `read -d '\0'`, just to name a few. Also many APIs require '\0'. It is the common string terminator, and strings are the most important data elements, since anything can be converted into a string. Therefore you want strings to be as flexible as possible. – Andreas Spindler Jan 26 '12 at 11:19
6

There are some APIs that expect a "string array" with multiple zero terminated strings, a double zero to mark the end. Raymond Chang just recently blogged about it, most of all to demonstrate how often that this gets fumbled.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536