Should I switch to C++ I/O streams? [closed]

廉价感情. 提交于 2019-12-03 12:20:55

I'm not a big user of streams myself, so I'll only list what I think about them. This is really subjective, I'll understand if my answer is voted for deletion.

  • I like : homogeneity

I may have a enum, a class or anything else, making my user defined type printable is always done by providing the same operator<< next to my type :

std::ostream &operator<<(std::ostream &, const MyType &);

You may ask yourself if a type is printable, but never how it is printable.

  • I like : abstraction

Obviously, it is incredibly easy to provide 'streaming capacities' to a user defined type. It's also a great to be able to provide our own implementation of a stream and have it fit transparently in an existing code. Once your operator<< are appropriately defined, writing to standard output, a memory buffer or a file is trivially changeable.

  • I dislike : formatting

I've always thought iomanip to be a mess. I hate writing things such as (I'm just throwing random manipulators here) :

std::cout << std::left << std::fixed << std::setprecision(0) << f << std::endl;

I think it was much easier with printf, but Boost.Format is helpful here.

Use boost::format. It's got the best of both worlds.

The massive advantage that iostreams offer is safety. printf() is an inherently unsafe function. Not just that, but it's trivial to overload << for your own types, whereas it's realistically impossible to extend printf()- this has the added advantage of instantly overloading for output to files as well, and anything else connected to a stream. In combination, these make printf() unusable in high-quality code. I've also noticed absolutely no performance difference, although I see many people posting about how slow they are.

@Matt, I'm with you. I've always hated streams. Sure, I can use them. Make them do pretty much anything I want. But I like printf because I prefer the syntax.

I even wrote a strprintf that worked exactly the same as sprintf except returned a std::string instead of writing to a char buffer.

But gradually, begrudgingly, I have almost completely stopped using sprintf. Because, simply speaking, I write too damned many bugs and I get sick and tired of going over and over my same mistake time & time again. stringstreams type safety saves me from myself.

The bugs I'm talking about for me come in 2 forms, mainly:

  1. I picked the wrong magic number for my output buffer. Say I come up with char buf_[256] to format up a little something. Well, just like Bill Gates famously attributed comment that "256KB of memory ought to be enough for anybody," I'm wrong on the low side enough to catch my eye. On the other hand, what am I going to do? char buf_[1024*64]? Extreme, but you get the point. There's no perfect magic number. You either expose yourself to more crashes, or you waste memory.

  2. I sprintf-ed a string, but sent it a float. Do this all the time. Well, not all the time. For every 100 calls to sprintf, I probably do this once or twice. For production code, that's a lot.

With streams neither of these can ever happen. So I use streams now, and my code never crashes. Well... there, anyway.

Some will say that streams are slower than sprintf. Eh, maybe. For the sake of argument, I'll even just go along with it. Doesn't matter much though. I work on real-time stock market servers that routinely process 3 million messages per second, all day long. And I've never had a problem with the speed of streams. Maybe it's a little slower, but I've got bigger fish to fry.

You cannot extend printf with new format specifiers to handle your own types.

You get more protection against type errors with C++ I/O streams, but they are SLOW. So it mostly depends on how important performance is.

I/O streams are also polymorphic, unlike the C stdio functions, the user of a stream doesn't need to know whether it's connected to a console, file, or some other logic. But this isn't important for most applications.

cuteCAT

I switched to iostreams after I learned C++ 10 years ago. Several years ago I was convinced that it was a bad choice so I switched back. I did not regret the switch. For a good C++ programmer you need to know both.

Google C++ style guide prefers to use printf/sprint/snprint over iostreams. It says to use iostreams only for logging.

In terms of iostreams benefits:

  • Type safety. Compiler (gcc) can detect type errors, as well as all static analysis tools. Even there is a type error, one can spot the error easily from the print out.
  • Extensibility. Yes iostreams have overloading but all data members eventually go to POD types.
  • No buffer overrun. Use snprintf to overcome the buffer size issue.

Now come the benefits of sprintf:

  • Much better readability. "Record(%d): %s\n" is much easier to read than os << "Record(" << i << ") " << msg << endl;
  • Performance. If you are doing a lot of iostreams stuff, changing them significantly improves performance. I once worked on a library that uses stringstream to convert int/doubles to strings. I replaced with sprintf and performance has improved a lot (there are a lot of calls to the conversion routine). For the record, boost::format has even worse performance.

My conclusion is that to use iostreams sparely. I use it to read memory buffer, or write to memory buffer occasionally. For other work, I use plain C function.

To follow up on Noah's answer, boost's format library allows for several different syntaxes, including printf like syntax. It works by overloading the % operator, and so at first appears a little strange. But, something I rather like, it allows you to reuse arguments. For example

cout << format("%1% %2% %1%") % 1 % 2 << endl;

will print

1 2 1

It's pretty versatile and if you can get used to the % signs everywhere, gives you the best of both worlds. As I agree, printf style is often much much easier.

http://beta.boost.org/doc/libs/1_43_0/libs/format/doc/format.html

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!