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?"
Depending on your compilier, you might end up with excessive binary-code bloat, as three different copies of "list" are created for list<foo*> , list<bar*>, and list<fred*> instead of using a single specilization for all three.
I don't know how well the inheritance issues are nailed down, but I've never been tempted to make a class inherit from a container, I just have classes have containers.
That said, I like STL and highly suggest using it. Never write a linked-list again.
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.
The biggest drawback of STL is finding something to do with all the extra time you'll have. Just think--you won't spend days debugging somebody's insanely API'ed String implementation he developed when wired to the gills on Jolt.
You won't spend discouraged hours in meetings while ego-driven idiots argue over whose pet collection class hierarchy better suits the hypothetical abstractions of the project. You won't waste precious energy trying to reverse-engineer someone else's pattern building-blocks because now you immediately recognize STL method signatures.
STL reduces job security for programmers who rely on obscure implementation. Some may see that as a drawback. IMHO, good code is maintainable code, and STL usage in any project is a quantum jump towards maintainability. Remember, the "maintainer" will probably be yourself revisiting the code six weeks after that all-nighter.
Remain calm! All is well!
1. It uses templates. I know the name implies this but I can't stand the way C++ implements templates. Templates are created at compile-time which removes any advantages of generics in the first place.
As compared to what language??? C++ templates are one of the best features of the language. Yes, they are a different concept, but embrace it, change is good.
I have no idea what you are talking about regarding templates being created at compile-time as being a bad thing. That's what generic programming is all about!!! Its the compiler generating classes so that you don't have to. It has to be done at compile time. I'd love to hear an example of a language that implements some kind of generic stuff at runtime.
2. While it may reduce developer time, it doesn't reduce code bloat. Templates are huge wasters of memory. This is because C++ creates a brand new class for *each* type of the template you use. So if memory consumption is an issue for you (like it is with me) then stay away.
Having additional classes only uses more memory at compile time. It makes absolutely no difference at runtime. The executable size increases only because of debug information. Stripping out the debug info will dramatically reduce executable size.
3. Template are *not* portable. Each compilier has varying support for templates. Yes the *new* compiliers support *most* of the STL but if a developer wants to get to those older models on the shelves... stay away.
ANSI C is *not* portable either for the most part. Remember, C++ is a young language with a young standard. Of course its not as portable as C, but its still more portable than any other solution (MFC, RougeWave, etc).
4. Using templates is verbose especially when you decide to throw inheritence in there. Template may look cool but they can get complicated really quickly (i.e. using the STL map template while inheriting from it)
YOU SHOULD NEVER INHERENT FROM AN STL CONTAINER. Period. There is no good reason to do this. If your design calls for it, then you have a bad design. Besides, STL containers do not have to have virtual destructors so you are introducing potential memory leaks if you inherent from them (this was made part of the standard on purpose).
5. Fragile Base Class. This is a C++ problem but it very much applies to the STL. If you build anything upon the STL and they add a virtual function... good-bye binary compatibility.
The STL does not have virtual functions. Nothing to worry about there. Remember, STL is standardized so there is no need to worry about stuff like that.
I fight extremely hard to not use the STL as there are other well-tested non-templated implementations of what the STL has.
For instance??? You are doing yourself an extreme disservice by avoiding STL.
int func(int a);
func((b += 3, b));
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.
the syntax and readability are so horrible that it took several computer scientists years to decide exactly how butt ugly and unreadable to make it.
STL is not, in any way, shape, or form, a step forward for programmers.
people can write stuff with it that is totally incomprehensible to anyone who is not party to their school of programming style -- but this is true of C and C++ in general.
I don't know what the solution to programming's difficult problems with reliability, reusability and maintainability, but I think Java has done a lot more to improve the state of the art in programming models, especially WRT these problems, than the STL.
Treatment, not tyranny. End the drug war and free our American POWs.
See my user info for links.
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.
Very true... I learned C originally in DOS and it worked fine there, but I haven't touched it much in recent years. I just recently started an embedded project, and decided I didn't have the patience to use assembly, so I jumped into the world of embedded C for the first time. It's a hell of a lot easier than assembly, stays quite tight with a bit of care (sprintf used up 80% of my available program space), and after dealing with a system having only 192 bytes of RAM and no OS I've got a much better appreciation of how the whole thing works. Stuff that seems like a major limitation after working in other high-level languages suddenly makes sense when you're coding on bare metal.
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
The most well-known example is using the sort algorithm instead of C's qsort. Because all the comparisons are templatized, and you never end up casting anything to void*, all the comparisons are inlined, and sort shames qsort.
When I tried it last, I didn't get the 6x difference some people claim, but it was about 2.5x faster.