Downsides to the C++ STL?
craybob queries: "I'm a developer for a small software group that will soon migrate from using Rouge Wave to using the C++ STL. I just left the week-long Software Developers 2002 conference, where I heard the great minds in software tell us all of the best ways to take full advantage of the STL. (I just wanted to give a quick thanks to Stephen Dewhurst and Scott Meyers) From this I came away with the feeling that this is the Holy Grail of C++. I'm sure these guys are right and that it is great, but the truth is that I'm a skeptic, so what are the downsides to the STL?"
The benefits of using STL are wonderful. If you write your custom containers/streams/etc. using the STL interface, you can seamlessly use the algorithms portion of the library.
I recommend reading the first part of Generic Programming and the STL. It'll help you undestand the thinking behind the design.
Unless there was a specific requirement and good reason for it, I wouldn't write C++ without STL nowadays. We've been using it for the last 2+ years on about 6 different unix platforms (mostly gcc2.95 over that time) and NT (using VC6.)
In that time we' ve seen a lot of improvement as native compilers for HP, and possibly IBM are catching up and threaten to replace gcc for builds on those systems.
VC6 is a real catch.. their STL implementation is only borderline usable. The solution to this was to introduce stlport into the mix, at least for our win32 builds.
Some issues we've had:
- verbose syntax (once your finger macros catch up, it's okay)
- EXTREMELY verbose compile error statements - especially when using a sufficiently complex STL object (vector of strings, or something) and doing something like attempting to use a const iter in a non-const way produces monstrosities like:
passing `const string' as `this' argument of `class basic_string,__default_alloc_template > & basic_string,__default_alloc_template >::operator =(const basic_string,__default_alloc_template > &)' discards qualifiers
(and that's a simple one.)
- Bugs on various platforms, including the lovely uselessness of VC6 STL
- Difficulty of examining data in debuggers - ddd+gdb gets a right ugly mess
- Memory High-water-marks: Some things don't really free the memory you want them to free, just hold onto it for next time. We've discovered this when we create stupidly-large temporary maps, and then delete them.
- Various little gotchas like the dangers of using remove() algorithms, being aware what map's operator[] does, etc.
- Inconsistencies between std::string and the rest of the STL
But to try and be less negative:
- STL has made handling data within a C++ program much more pleasant. For us, STL is fast and efficient, and has probably saved us many programmer-months in the debugging and development time required to use traditional C/C++ data structures. Plus, once you get into the mindset used by STL, it gets more and more powerful every time you read another part of the documentation.
In practice, the big problem with the STL is that Microsoft doesn't like it. It's one of those standards that Microsoft doesn't control, yet is so widely used that they can't ignore it. So they support it, but badly. (OpenGL gets similar treatment. So does C++ itself. Microsoft prefers their own dialect of C++, which is not fully compatible with the ISO standard.)
The STL doesn't help too much with the big problem of C and C++ programming: keeping track of who owns what. auto_ptr and the STL don't play well together. That's a lack, and it's not easily fixed. There have been three iterations of auto_ptr semantics, all of which have some painful problem. See "comp.std.c++" for discussions on this subject.
If you are a good computer scientist there are no real downsides. If you are just hacking a system together and don't understand how the datatypes and algorithms work, and you don't have time or care to read the manuals, you will be in trouble using the STL.
I have used several versions of the STL on several compilers and OS's, and find that as a whole, the STL has few downsides, **IF YOU READ AND UNDERSTAND WHAT IS GOING ON** If you don't understand the basics, it becomes a nightmare to debug. On the flip side, if you understand what is going on you can get very fast code at low development cost.
Developers need to understand that certain operations invalidate iterators, and things like that. (That is the most common error that I see.) When you get an error in STL code, usually it shows up not as a single error but as a huge list of errors as it propogates through the template library -- but it is just one coding error. You might consider those as downsides, but they are typical in computer programming.
A lot of people listed 'bugs', slow learning rate, and other problems, but in my experience the STL is easy to use if you consider the two aspects the STL covers -- data types and algorithms. I have seen other programmers struggle because they cannot separate the two. They think that string types should have string algorithms in the class, or sets have the set operations, and so on. The STL is an attempt to keep the two apart. It is easy to write new data classes that use the STL by implementing the few functions needed for all the algorithms, and it is easy to write new algorithms that use any STL object because they all implement the same small set of functions.
One example -- It is easy to change the allocation method (swap portions of ram to disk) simply by writing a new allocator. A co-worker insisted that the STL wouldn't work outside of RAM, but a simple allocator class allowed everything to work on disk for huge data stores. The co-worker had spent years working on implementing a few slgorithms and data types on his own. The STL with a simple, custom allocator worked faster than his code, and took much less time to develop. Poor guy -- I really felt sorry for him.
There are some problems with specific older compilers, but most are fixed. The older Metrowerks compiler didn't allow traits, the older Microsoft compiler didn't allow several kinds of nested types (use the service packs to fix them) and their debug info is terrible in VC6, GCC used to generate very bad STL code (it still has some quirks). The glitches are mostly fixed now. New, GOOD compilers will take longer to compile (downside) but will often generate either smaller code or significantly faster code (big benifit). I have seen cases where the executable doubled in size (the code bloat that people talk about), but the runtime decreased signficantly (not usually mentioned), and the code became much more readable. Since most of us (except embedded systems people) don't need to worry about size, the tradeoffs are acceptable.
Another benefit/downside is that if you use optimizing compilers that know about the STL, you can do really incredible things. For example, if you are using a valarray (value array) type to perform operations, you can get massive speedups. I use the Intel Optimizing complier for x86 chips, and it uses MMX, SSE, and SSE2 optimizations to perform many loop, array, and STL operations. It is cool to see huge sections of code the the compiler message "foo@bar@PARAM@Z has been selected for automatic CPU dispatch", and reading the generated code shows that it uses the MMX or XMM registers, depending on the CPU type, or use the slow, loop based values on 486/Pentium chips. A bad compiler would probably just go to the worst case, the slow loop -- so get a good compiler.
Itanium chips could do extremely well on many of the STL algorithms. (I have wondered if the Intel Optimizing compiler for Itanium would do massivly parallel ops with valarray classes. Does anyone have experience there?) Other parallel chips can benifit in this way as well, IF THE COMPILER IS SMART ENOUGH TO DO IT. The downside is that you have to know how things work and why. If the compiler doesn't do the optimization, perhaps another algorithm would work better in that case.
//TODO: Think of witty sig statement