Slashdot Mirror


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?"

26 of 946 comments (clear)

  1. One Downside by jsonic · · Score: 5, Funny
    but the truth is that I'm a skeptic, so what are the downsides to the STL?

    It's written in C++? :)

    1. Re:One Downside by rjh · · Score: 5, Informative
      I've been using C++ since 1989. I'm still learning more about C++ today.

      It always amazes me at how people who acknowledge they don't know C++/STL (as you said, "I have never used it") know so much more about it than those of us who've been using it since the mid-90s, and who still discover more neat things about it on a continuing basis.

      That said: C++ makes it easier to produce bloatware.

      Two answers:
      • Yeah, so?

        Name me one advance in computer science that doesn't also carry with it the possibility of using the advance stupidly. Yes, if you deliberately do stupid things with C++, you'll get code bloat. But if you make the language impossible to do stupid things in, you'll also make it impossible to do clever hacks in the language. If I want a language like that, I'll use Java, thanks.

      • Have you seen what that `bloat' does?

        Most of the time when people blame code bloat they're really blaming templates. Tell you what: look at the vector template and find out just how brilliantly sweet it is. Now hand-code it in C, such that it gives you the exact same level of sweetness, speed, and safety. Dollars to donuts says your C code is more bloated.


      ... and it has the added disadvantage of objects.

      Spoken like someone who never made it past the introduction of Stroustrup's The C++ Programming Language. Repeat after me: C++ is not an object-oriented language. C++ never was an object-oriented language. C++ never will be an object-oriented language. C++ supports OOP, but that doesn't make it an OOPL. C++ is, more precisely, a multiparadigm language. You want generic programming? C++ has the tools. You want functional programming? C++ has the tools (awkwardly, but they're there). You want OOP? C++ has the tools. You want procedural/imperative programming? C++ has the tools.

      Whatever you want, C++ has the tools.

      Hey, at least its not Java which forces OOP on you instead of giving you an option

      My harsh words about Java (above) were, as I hope the Java community will understand, meant as a gentle jab from one diehard C++ hacker--not as a misinformed flame like you're spewing here. Of course Java gives you an option. If you don't want OOP, don't use Java. Use Ada95 or Python instead, both of which support non-OOP paradigms and which can compile down to Java bytecodes. Java, like Smalltalk, is a purely OO language. Saying that Java sucks because it forces you to write OO code is... well, really foolish. Java doesn't force you to write OO code; you force yourself to write OO code by committing to Java as a platform. Java is a tool in the toolbox. A hammer doesn't force you to treat everything like a nail; but if you choose to pick up the hammer, the only person to blame is you if you needed to pick up the screwdriver instead.

      I can't really talk about the STL

      ... Why not? Your utter ignorance didn't stop you from talking about C++ or Java.

      ... but from the coders I do know who have used it

      ... And are these coders competent craftsmen, skilled in the ways of the STL? Or are they incompetent two-bit fly-by-nighters?

      it is a sad sad mechanism for making your code slower and harder to debug and your executables larger

      Bullshit. Look at the following code:

      /* C version: sorting random 1M-element array */

      int compare(const void* first, const void *second)
      {
      int *x = (int*) first;
      int *y = (int*) second;
      return x < y;
      }

      int main(void)
      {
      int array[1048576];
      qsort(array, 1048576, sizeof(int), compare);
      return 0;
      }

      // C++ version

      int main(void)
      {
      int array[1048576];
      sort(array, array+ 1048576);
      return 0;
      }


      [rjhansen@numbers cpp]$ time ./c_version

      real 0m1.034s
      user 0m0.960s
      sys 0m0.070s

      [rjhansen@numbers cpp]$ time ./cpp_version

      real 0m0.719s
      user 0m0.720s
      sys 0m0.010s


      ... Want to repeat that bit again about how STL causes your code to run slower and be harder to debug?
  2. Not all compilers support it, god-awful comp errs by Avumede · · Score: 5, Informative

    The fact that no compilers support all of STL is admitted by Stroustrop (sp?). However, in practice, most of it indeed works as advertised. You shouldn't have much problem.

    But the real bear is the compilation error messages, which can be pages long, and ultimately completely unreadable. This is due to template expansion, especially with STL classes (most of them) that take a large number of arguments, most of which have default values already.

    Also, as with all templates in C++, there is code bloat. But it is a tradeoff between having more code or having better type checking. You have to decide what is right for you.

  3. Not many by Xentax · · Score: 5, Informative

    In terms of usability, the STL is great. I've been told that it's not the be-all and end-all as far as performance goes, but it can handle most applications, even situations where there IS a performance requirement as long as it's not an especially stringent one.

    We developed a call-routing application for Solaris in C++ using ACE and the STL, and were able to meet a fairly hefty performance goal.

    The biggest downsides on the STL that we encountered were a few compile issues in terms of integrating ACE into the build (not a big deal), and the larger one of somewhat poor documentation of the STL itself. We used the MSDN STL documentation, and while Microsoft's implementation may agree with that API spec, Solaris' certainly didn't. See the signature of the map::delete method for an interesting example.

    Both the Solaris (actually SGI) and RogueWave implemementations DO NOT match the documented interface, even though Rogue Wave's documentation says it does! So make sure your intended usage is actually supported by the implementation of the STL that you're using.

    Xentax

    --
    You shouldn't verb words.
    1. Re:Not many by Xentax · · Score: 5, Informative

      Oh, one other thing:

      Pay attention to which operations are expensive for the various data structures (map vs. list vs. vector, etc.).

      The fact that the operations' syntax for each of these is standardized is a double edged sword -- it makes for clean code and syntax, but it can mask poor-performing operations. Consider iterating over a map vs. over a list, for example.

      So, consider carefully what operations you perform on various structures, and (of course), profile where/when appropriate. Looking at the actual implementation of the STL you choose can go a long way in revealing such troublespots, if that's an option (SGI's implementation is pretty easy to get ahold of).

      Xentax

      --
      You shouldn't verb words.
  4. Re:Lots of overhead. by emount · · Score: 5, Informative

    The C++ language spec explicitly specifies the performance requirements for STL components (which is rare in a language spec, IMO)... the brunt of the work is at compile time, and there is no virtual function dispatching in the STL.

  5. Not many drawbacks by emarkp · · Score: 5, Interesting
    I've been happily using STL for about 3 years now. The biggest drawbacks (IMO) are:
    • Kitchen sink syndrome: There are a lot of features in STL, and to use some of them you need functors, etc. Sometimes it's just easier to read if you use a normal for loop instead of using for_each, etc.
    • verbose type syntax: When you use the containers, like (say) std::vector, you have to declare your iterators as:
      std::vector<int>::iterator i;
      If you change to a std::list container, you'll have to change your declarations. Of course, you can mitigate that by using typedefs, and then you only have to change the typedef, but it can still get a bit wordy.
    • unexpected results: Understand the difference between remove() and erase() in the containers.

    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.

  6. Check out "Effective STL" by Myers by lkaos · · Score: 5, Informative

    The last book in Myers effective triology goes into a great number of details about the pitfalls of STL

    One thing to be wary of (as many have pointed out) is the different implementations of STL. GCC pre-3.x is pretty non-standard (although not necessarily bad). MSVC pre-6.x is absolutely horrendous (from what I gather, this is more of a legal issue than MS's fault).

    Some of the wackiest things though IMHO are:

    - Never use vector! It's a horrible specialization and is not even a container. Very, very bad.

    - Allocators are for the most part evil. Be very wary of them.

    BTW: There is a book Efficient C++ that says a lot of bad things about STL. This book absolutely sucks and is full of nothing but crap. While the examples aren't forged, they are examples of how not to use STL. Unfortunately, the book presents non-STL solutions that aren't even as fast as the proper STL solution. Long and the short of it is, make sure you (and your developers) are very familiar with STL and be aware of bad information about it.

    --
    int func(int a);
    func((b += 3, b));
  7. Partial List by Viking+Coder · · Score: 5, Informative

    Before you listen to any of us, go out and buy "Effective STL" by Scott Meyers, and probably "The C++ Standard Template Library" by Nicolai M. Josuttis.

    Now, I don't want to get off on a rant here, but in my personal opinion, the worst thing about STL is their string support. It's great, because it's standardized, but that's about the only thing going for it, from a programmer's perspective. (Yes, it's highly optimized, but the API isn't very rich. I like rich APIs!) In other words, build your own string class, and give it a Has-A relationship to the STL string.

    Also, I hate that Containers change paradigms on you, some places you can use integer indecies, sometimes you have to use iterators - and in my opinion, the line isn't very clearly drawn.

    Also, the methods are written along the lines of, "if it's not optimal, you have to write the code yourself." I'm sorry - that sucks. Sometimes I need to remove an element from a Vector. Maybe I should be using another Container. Or maybe the API should allow it, but make it clear in the documentation that it's not efficient. I vote for the latter.

    Get used to having your objects copied. STL Containers work by copying your objects. It's a different way of thinking for a lot of people. It has rammifications that are kind of hard to grasp, at first, if you're not used to it.

    Don't use Containers of AutoPtr's! It won't work right! (Read "Effective STL" for an explanation.)

    In my opinion, everyone should wrap every third-party library they use with an API that they can live with. STL is no exception. You might even expose every single member function, but you have the freedom to expand your API if you want. If you can't afford a stack push, then you probably shouldn't be using STL in the first place.

    If you end up really liking STL, take a look at Boost. Some parts of Boost are really cool and well written.

    Really, I think the best advice I can give is this : get to really know an API before you start to use it. Because, if you try to just use the parts of an API that you know and like, you're going to make horrible mistakes. Invest the time to get to know the library well enough to use it the right way. STL is no exception.

    Of course, that's just my opinion, I could be wrong.

    --
    Education is the silver bullet.
  8. Bad inline optimisation. by Phil+Wilkins · · Score: 5, Informative

    The main problem with the STL is that it relies heavily on inline functions, and many compilers (GCC included) still have very poor inline optimisation. The GCC variant we use for the PS2 (ee-gcc) has a terrible habit of inserting spurious writes back to memory, causing all sorts of unnecessary stalls.

    Perversely enough, despite the unreadable and buggy implementation shipped with it, Visual C actually produced remarkably good object code from it. The vector class in particular was more efficient than many of the hand-rolled examples I've witnessed during my career.

    ...

    Virtual functions, as others have noticed, are a complete red herring, as the STL doesn't use them, and any moderator with an ounce of sense would mod parent down for being uniformed karma whoring bollocks.

  9. Enterprise issues with STL by MobyDisk · · Score: 5, Insightful

    I am an avid user of STL, and I have worked on many projects, large and small, that make use of it.

    Advantages of STL:
    - Standardized, comes with every C++ compiler
    - Fast
    - Generalized (excellent use of templates)
    - Many different implementations freely and commercially available.
    - Source code available.

    Disadvantages of STL:
    - Large executable file sizes
    - Incompatibilities between implementations
    - Complex to debug

    STL is a very fast and powerful library. Ignore those who say "it uses virtuals, and is in C++, therfore it is slow" because none of them have ever used it. (C++ is in fact faster than C if coded properly, and STL is coded properly) Often, a good structure is much faster than using arrays, even if they have less overhead.

    Unfortunately, STL's use of templates and inlines can inflate the size of your code in exchange for raw speed. This can vary very much depending on your compiler. MSVC adds 200k or more just for the priveledge of using strings! Using STLport still requires that you link in the old 200k libraries ON TOP of STLPort!

    I do not recommend using STL on small projects where compiled file size is an issue. For anything else, go for it.

  10. Vendor specific by Zathrus · · Score: 5, Informative

    The biggest downside of the STL is when it doesn't work.

    Sure, the standard is >3 years old now, but a lot of compiler vendors are still working out bugs with either the STL, their compiler, or their linker still.

    Under AIX, we've run into relatively few problems with the STL itself, but the linker is pretty bad. Between it and the compiler compiles take forever (which is why I've been surfing /. more recently), and the executables are freaking huge.

    This is, obviously, an AIX-specific problem. And it's pretty much an old story - every vendor has their own quirks with the compiler and/or linker.

    Beyond that -- I've found a few things missing in the STL that would be really nice to have.

    First, the only smart pointer is std::auto_ptr. It's pretty useless, since you can't use it in a collection, and you can't have more than one thing pointing at an object/memory block at once. This can be worked around though, since there are libraries that have better smart pointers. Check out Loki or Boost for two.

    Second, there's no way to automagically ignore case on a std::string, or to upper/lower case it easily. Yes, I know, you can muck around with traits, but that's a PITA and renders your string uncopyable to other strings easily. Yes, I also know that you can use a transform() to do it. But this still isn't as nice as myString.lower().

    Third, there's no date or datetime classes. You have to fall back on C time functions for them. I haven't looked for a good C++ library to handle date/time, but I'm sure there's one out there.

    Fourth, there's no regular expression matching on strings. We use PCRE with a C++ wrapper and it works fine for what we need though.

    Both 2 and 3 are due largely to internationalization issues... in the case of 2 there's a lot of languages in which upper and lower case are non-sensical. And after having thought about the i18n issues regarding dates, I don't blame the standardization committee a bit for running away screaming from them (what date range? which calendar? how do you change between calendars? what about date weirdness with some calendars (like the missing days in the Gregorian calendar)? etc).

    I used RogueWave prior to this job, so I tried to think of some of the things I was used to in RW and weren't in the STL. By and large I prefer the STL though. The container classes in particular are a lot more sane than RW's.

  11. Advice from an STL battle-scarred veteran by MagikSlinger · · Score: 5, Informative

    First off: Why must you use STL? STL can be handy, but it can also be a terrible pitfall to the unwary. If your code is working and there is no compelling reason to re-write it, then don't/

    Secondly: Be very, very careful about using pointers to dynamically allocated objects. If you are copying pointers around, you could very easily get into a dangling reference. A smart-pointer template (which SHOULD have been part of the STL) is a handy thing to have.

    Third: Take the time to learn the Zen of STL. You must understand the rationale and mental model of the STL to get the most out of it. It doesn't take long (a week at worst).

    Fourth: Get a good C++ and STL implementation. If you don't, you could wind up with compile errors that will drive you insane. <Sounds like the voice of experience, MagikSlinger!>

    Fifth: Use STL sparingly. Don't go hogwild creating types made up of a dozen composited templates. When you get a run-time error or compile error, it becomes next to impossible to decipher what happened. Do not go more than two levels deep in an STL definition. map<string,MyClass> is OK, map<string,map<pair<T,X>,list< vector<int>>> is a very, very bad idea...

    Sixth: Use the simplest datatype to achieve your goal. Don't resort to multimap, etc. with fancy indexing/hashing schemes unless you prove emperically that it will speed something up a lot. Not a little bit, but a lot.

    Good luck, and have fun!

    --
    The bitter lessons of a veteran coder: http://bitterprogrammer.blogspot.com
  12. It is hard to learn well by Henry+V+.009 · · Score: 5, Insightful

    You've read Meyer's book, which is a good start. You probably also want to check out Josuttis.

    The STL is really as good as could be expected. Better even. There are problems. Some problems stem from the fact that it had to be approved by the standards committee. There was a lot of opposition to adding something that big to C++, so the size was cut down. Certain things are missing. (Heaps, general binders, good smart pointers) but versions are provided by many implementations. Check out CGI for one. They will also be added to the next version of the standard, along with a few other nifty things (As always check out boost.org for much of that stuff). The allocators are broken in my opinion. Using (different) customized allocators prevents interactions between your containers.

    The biggest problem is its complexity. Like any C++ feature, understanding the STL is not enough. You need to understand how it interacts with other parts of C++. When you use the STL, you are using a rocket launcher instead of a BB-gun, shooting yourself in the foot can be much worse.

    All in all the STL is god's gift to programmers. It really is. I can't imagine not having it to program anything serious with. I work everyday with AI and Image Processing algorithms -- stuff where performance really counts, mind you -- and I couldn't live without the STL. I barely use pointers anymore.

    To sum it up, C++ with the STL is the only language that meshes (not always prettily) performance computing with high level concepts. It is a truly beautiful technology.

  13. Re:the STL is imporperly named by ivan256 · · Score: 5, Insightful

    As with OOP itself, generic programming is a Really Good Idea(TM)

    Be careful. It's generalizations like this that end up in the hands of managers and can lead to Really Bad Software(TM). There are plenty of cases where a small generalized solution is more apropriate. THere is no golden paradigm for software development.

  14. Re:Not all compilers support it, god-awful comp er by Mike+Connell · · Score: 5, Informative
    Just for the non C++ programmers, here's a (real) example of those STL template errors.
    readply.cpp:109: conversion from `_List_iterator<list<basic_string<c
    har,string_ch ar_traits<char>,__default_alloc _template<true,0> >,allo
    cator<basic_string<char,string_char_traits &l t;char>,__default_alloc_tem
    plate<true,0> > > >,const list<basic_string<char,string_char_traits&lt ;
    char>,__default_alloc_template<true,0> >,allocator<basic_string<char
    ,string_cha r_traits<char>,__default_alloc_template<t rue,0> > > > &,c
    onst list<basic_string<char,string_char_traits&lt ; har>,__default_alloc
    _template<true,0> >,allocator<basic_string<char,string_char _traits<c
    har>,__default_alloc_template<true,0> > > > *>' to non-scalar type `
    list<basic_string<char,string_char_traits&lt ; har>,__default_alloc_temp
    late<true,0> >,allocator<basic_string<char,string_char _traits<char>,
    __default_alloc_template<true,0> > > >' requested
  15. Re:What virtual functions? by lkaos · · Score: 5, Informative

    The number of abstract data types IN NO WAY AFFECTS CODE SIZE. Sorry to say it loudly but too many people here keep repeating that.

    It may *appear* that way when working with STL but that is only because of the debugging information. Using templates will increase the amount of debug information in the executable (for each instance of the template) but it does not increase code size in any noticable manner.

    Note: Ok, there are some methods that do get regenerated per-data type but the overhead is small and STL uses extensive inlining so this is almost meaningless.

    --
    int func(int a);
    func((b += 3, b));
  16. Re:the STL is imporperly named by SLOGEN · · Score: 5, Informative

    > The biggest downside of the Standard Template
    > Library is that it isn't very standard.

    No, but the C++ Standard Library is in ISO14882 ("Programming Languages -- C++"), and it "superceeds" and embraces the old STL. Unfortunatly most people (and tutorials) still refer to either the STL definitions or use the term STL about the standard library.

    > The support for templating, across a range of
    > compilers, just isn't very consistant, which
    > makes using the STL in a portable manner
    > almost impossible.

    Depends on what you use. Normally, it's not the containers themselves. that makes trouble, it's the functors and the algorithmic versions of operators (i.e. std::less and such), which most programmers don't use for the first few months.

    BTW: GCC-3 has EXCELLENT template-YOUR_FEATURE_HERE support as well as standard library support.

    > Aside from that, the STL is, to my mind, just
    > another giant complex wart on top the
    > mind-numbing complexity that is ANSI C++ itself.

    C++ is complex because of the possibilities it offers... well, and it's heritage. To the untrained even the simplest tasks are compilcated... think how long it took to understand (not just learn) multiplication :)

    > As with OOP itself, generic programming is a

    Hmmm.... I consider generic programming perpendicular to OOP (this is a nice analogy when explaining why using GP from OOP sometimes requires "multi-dimensional" programming... if you understand?)

    > Really Good Idea(TM) but its implementation in
    > C++leave something to be desired for simplicity
    > ans accessability.

    Agreed, as well as consistence in compile-time versus runtime versions of syntax.

    > Due to C++'s dominance in the marketplace, the
    > STL will likely be with us for many years, but
    > this is far from a desirable circumstance.

    The Standard library (not STL) is the best thing that happened to C++ for years. I doubt it could have been done cleaner and more flexible in C++?

    I would like to see optional garbage collection (with fitting restrictions to legal programs) introduced into C++. That's the no. 1 thing holding back (advanced/modern) OOP in C++.

    --
    Helge

    --
    SLOGEN [ http://ungdomshus.nu : Sebastian cover music]
  17. Experience with STL on multiplatform by Tiger · · Score: 5, Interesting

    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.

  18. Debugging is the downside by baxissimo · · Score: 5, Insightful

    Your comment points to what I think is THE major downside to STL: debugging.

    If something's not compiling that you think should, you end up wading through the mile-long error messages. If it does compile but doesn't work right, you're going to find yourself in the debugger trying to step through some of that crazy obscure STL C++ code to try to figure out what the heck is going wrong. Neither is much fun.

    But when it does compile and run correctly STL is pretty nice!

    I'm looking forward to somebody starting over some day and coming up with a language that supports generic programming as well as C++, but which doesn't have the terrible syntax of C++ templates. It must be possible.

    Basically people have realized that templates can can be used to create programs that run at compile time to do some very clever optimizations (template meta-programming is what they call it see http://www.boost.org for one implementation. Blitz++ is the big example use of the stuff that everyone points too). But the code to make this stuff happen is ATROCIOUS!

    Yeh, you can make a template meta-program to calculate factorials at compile-time. Great! That sort of thing can come in handy. You can even write template meta-code that basically generates code at compile time. That's cool too! But the code to do it looks NOTHING at all like the equivalent run-time code. Why does it have to be that way? Why does compile-time code have to look SO different from run-time code, at at the same time look SO horrific?

    I think what is needed is a new language that will put compile-time and run-time code on equal footing. It would be great if they had the same syntax. Then you could just, say, change one line to turn some run-time code into compile-time code (only when there's no dependence on run-time data, naturally). But it doesn't necessarily make sense to put all the run-time efficiency restrictions on the compile-time language. Dynamic function lookup by strings is a pretty big run-time hit, for example, but you wouldn't care as much if it were used for compile-time function lookup.

    In general, the meta-programs seem work a lot more like functional languages -- so fine, I'd be willing to settle for at least a clean syntax for the compile-time language, say something Lisp-like, even if it looks different from the run time language. ANYTHING, as long as the syntax is clean and readable, would be better than the current situation of trying to do meta-programming in C++.

    I think the situation C++ is in today with respect to generic programming and meta-programming is a lot like where C was when OOP started to become big. People realized that, yeh, C can do OOP, but it doesn't really support it. C allows OOP, but it offers nothing really to facilitate its use. I think Stroustrup makes that argument in his C++ book. So Stroustrup created C++ as a language that would support OOP, not just allow it.

    Well folks, now we've got this handy meta-programming stuff, and yeh you can do it in C++, but it is not pretty. It's downright painful. Writing it is hard. Debugging it is hard. Testing it is hard. Reading it a week after you write it is even hard. Sounds to me like it's time for some new language stud to come and save us.

  19. The STL, by a longtime user by Animats · · Score: 5, Interesting
    The STL is a reasonably good collection library. I wasn't initially too happy with the iterator paradigm. The idea of generalizing pointer arithmetic, the most error-prone feature of C, seemed a terrible idea. But it's worked out moderately well, and STLport can be compiled with iterator checking, which is very useful.

    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.

  20. Re:Lots of overhead. by angel'o'sphere · · Score: 5, Informative

    LOL

    moded as interesting but plain wrong.


    but there is a lot of overhead with using the STL.


    No there is no overhead in terms of speed. The STL is designed to yield as efficient code as a VERY GOOD coder would get by hand coding. As the STL is coded with "how will the compiler work on this" in mind its often far more efficient than hand crafted code ever will be. (e.g. inlining over several function calls in depth)

    Virtual functions and things of that like can make your code bigger and slower.

    In the STL there are only few virtual functions. Most are non virtual.

    Also a non virtual call costs you about 8 bytes asuming a 4 bytes instruction and 4 bytes adress, where as a virtual call you cost about 16 bytes, load register with adress, two times 8 bytes and jump idirect with register and offset, again 8 bytes.

    However in practice the latter case is often only slightly bigger than the former(depending on the instruction set of the CPU).

    If the code will be bigger than without STL is a question how your compierl and linker treat templates.

    And it is a question how you would replace templates by hand.

    Regards,
    angel'o'sphere

    --
    Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
  21. * is faster than C (??) by Ars-Fartsica · · Score: 5, Insightful
    Every time someone trumps up the merits of their language, they always mention that it is (potentially) faster than C. This has been uttered so many times that I don't know why anyone uses C at all, it clearly has terrible performance (according to all the language advocates).

    I'm calling your bluff. Give me some stats for example programs.

  22. Downsides by Frobnicator · · Score: 5, Interesting
    This is a longer post and has taken a while. Someone might have already said this, so please don't mod me as 'redundant'.

    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
  23. /. is a skewed sample by LoveMe2Times · · Score: 5, Informative

    I just wanted to point out that asking about something like the STL here on /. will not give you much breadth of opinions on the matter. When it comes to programming and software development, /. has a high concentration of scripting language users for web site backends and administrative tasks, and a relatively small number of "application" developers. There are also a disproportionate number of systems programmers. From reading /., you might get the impression that C++ is not very widely used. While this is true in the Open Source world where there are many *many* more viable options, commercial software development is still pretty dominated by C++ with Java seeing use in some sectors. So what's the takehome message here? Even given /. bias, you're still getting a pretty positive response to STL. Anyway, here are a few things you should know:

    1) Get STLPort. Use STLPort. STLPort addresses many, many, STL issues. They add extra nice classes like hash tables. STLPort is thread safe. STLPort has nice extra debugging features. STLPort has readable code. STLPort is PORTABLE (thus the name!). OpenOffice uses STLPort, in case you're still dubious.

    2) Get a couple of STL books. There aren't any really good ones (IMHO), but it's handy to have a printed reference with some examples.

    3) You wanted downsides, so here's one. You will have to learn STL. Not the library, but the techniques--the API is easy. You have to write your own C++ classes well to take really good advantage of STL. The way you leverage the STL for absurd productivity is through generic programming and STL's pluggable component architecture. Still, though, even you all you ever use is map, string, and streams (or some other subset), you'll probably become a convert.

    4) STL will keep getting better to use. Other people have mentioned it, but look at Boost for some ideas about where STL is headed. Also, the compiler people are aware of and are working on the error message and debugging problems. Both VC++.Net and gcc 3.x are making progress here.

  24. Re:er... "horseshit" by IBitOBear · · Score: 5, Informative

    Why it is a well-designed language:

    (Summary first) Everything was put in or left out for a reason and that reason (per thing) is documented if you take the time to look. Since it will be impossible in this forum to address the entirity of the issue I will stick to the elementes you named. Specifically the four casting operators (actually there are five) and the constructor invocation as a sixth "cast", which you incorrectly classify as an ambiguity.

    First you must consider the base language construct of the unconditional cast.

    struct A { ... };
    struct B { ... };

    A * ptr_to_A = new A();
    B * ptr_to_B = (B*)A;

    In the base language "C" the above is legal, will compile just fine, and is totaly wrong. This program would likely fail catostrophically. This is the generic version of an actual problem we (at my company) just found in a comercial "C" product.

    The thing is, the C-style cast has some core functionality that is occasionally indespensible. (The discussion of when and how this is indespensible is ommited as whole chapters of books cover this topic.)

    More importantly the C-style cast is a "gloves off" operation. When the programmer performs this basic operations it is with the understanding that if it is wrong it is to be done anyway. Complaining about its existence is like compalining to a surgon that a scalpel is dangerous because it could cut something...

    The four "lesser casts" (my term) are "gloves on" operations. The programmer, in using the spesific casts is describing a desireable transformation on the data and the compiler and/or runtime checks the viability of the operations to ensure that they are completely legal.

    Consider first a language that will do silent uncasted transformations (C++ will do these in some spesific and well defined cases which I will get back to later)

    if you have "let SomeString = SomeInt" and the language allows this as a transformation (see awk, possibly Perl etc) it will "just do it." but the "it" is only vaguely defined. It is worse if "let SomeInt = SomeString" where there is no obvious guarantee that "SomeString" contains a useful representation of a candidate integer.

    Ok, so we can agree that the transformation of a datum from one intrinsic type to another is problematic. Composite types make this a composite problem. Now back to the casts...

    All the casts represent expressions in the true sense. The opperations are transformative just as unary minus or square_root are transformative. The original object and representation are unchanged but the address or constantness or the "invariant" are manipulated. And like any expression there may be temporary objects involved. Listed from most-checked and safe to least, the compile-time resolvable casts are:

    const_cast(existing_object) => the existing_object may only vary from the new_type by the addition or removal [usually removal] of the constantness.

    static_cast(existing_object) => the existing_object must have a defined pathway to becomming an object of the new_type. Usually this is done by one of two methods. The most common transforms the address of the object into the address of the part of the object that is of the new_type. The second method creates a temporary object of the new_type using the relevant information from the existing_object.

    reintrepret_cast(existing_object) => almost always a transition from pointer-to-existing_object to pointer-to-void or vice versa. The reintrepret cast is used to release the expression from the constraints of the invariant of an object. Usually in order to pass the object through some external interface (e.g. passing it to the OS etc).

    Notice that these three casts each have a spesific guarantee of function for form. To take the safe root through a transformation you sometimes need to use two casts together. Most commonly you will un-constant-ize something and then static cast it if you are doing these kinds of casts in a way that requires composition. I'll skip the example for now. The important thing is that you can, once you know how to use your tools, know in turn exactly the transformations that your existing_object or reference or pointer there-to will undergo.

    There is no uncertanty in the three compile_time casts.

    The fourth "limited cast" is:

    dynamic_cast(existing_object)

    This one is trickeir as it has an implicit "if" statement within it at compile time and another "if" statement in it at runtime.

    IF new_type is an obvious part of existing_object the dynamic_cast is identical to the static_cast and you should have used that. The compiler will use that static_cast in place of the dynamic_cast because it knwos you are being dumb. 8-)

    IF however new_type is not clearly in existing_object(s) ancestory (this is the "else" of the above case) then the compiler generates code to deal wiht the cast at runtime instead of compile time.

    At runtime, IF the new_type object that is "part of" the "whole_object" that existing_object might also just be "part of" then the whole thing goes off without a hitch and the expression works. If the request is impossible then either a zero is returned (remember "transformative expression" 8-) or an exception is thrown. (the causes and cases are again ommited, go read the book).

    SO BACK TO THE CORE QUESTION: Why is the above a "good language design"?

    Answer: Because an unconditional cast "(new_type)existing_object" could do any combination of the above, but the above only happen explicitly if you use them explicitly.

    Hua?

    Well, in the first three you *ALWAYS* get a thing of the type new_type so there is no testing to be done. The compiler will not let the activity go wrong. You don't have to test anything in the code, the compiler makes you a warrent.

    The fourth, more dangerous and occasionally indispenseable and often quite desireable, cast needs support code.

    In a lesser language, I would either have to inclde the support code for every cast *OR* "work without a net".

    In C++ I can code to the spesific requirements.

    A language that lets the programmer code to the spesific requrements without having to put in lots of dead code just to be safe is "well designed".

    Some languages "seem" to be better designed because they put in the general case safety-net for you, but languages that generate "general case" code "for you" arn't well designed. The fact that some environments/compilers then try to take the safety-net code back out durring optimization etc are arguable. The work for the slapdash at the cost of allowing the programmer to express himself explicitly. When the programmer isn't really in charge of the code that is generally a "bad design" where effeciency is a factor. But for the people who need this net or don't know how to work without it, this kind of code is "good".

    But I digress.

    So what about the so-called "ambiguities" over constructor invocation as a casting operation.

    First, construction of a new object isn't, strictly speaking, a cast operation. It is "so like a cast operation" that in practical terms the two operations are considered synonymous.

    In actual fact, construction is construction. Casting is casting. Construction is the building of a new object using the information from zero or more old objects. Casting is the reconsideration of an existing object "in place".

    The confustion arrises because a sloppy thinker often cannot separate the classification of an object from the application of the value of that object.

    In the expression "A = B;" A is being transformed. In the special case "A_Type A = B;" the transformation of "starts from nothing". The construction of paramter objects durring fuction call is the latter case.

    The language allows us to define the transformation of A with respect to many types. If we create a transformation of A based on a B then this is obvious. Sometimes things are not that simple.

    The programmer is allowd to make a chain of transformations implicit in ther code space because the language design allows for one "free and silent" step to be added. That is, if B can become X and X may be used to transform A, then B will transform A by way of a temporary X.

    The user is spesifically warned that this feature must be used wiht due dilligence. In particular if there is more than one possible X intermediary the compiler will pick the "best" one. The rules for finding this "best X" are explicit (there are exactly four such rules).

    Additionally, under no circumstances will B => Y => X => A considered.

    If there is more than one "X" and they score the same on the "betsness" scale the compiler will demand the programmer clean up his mess. Many less-well designed languages will silently pick one wihtout a peep, which one may change from compile to compile. This would be an inferior design because any "X" may have larger-scale implications.

    The educated user is capible of making the transformations work seamlessly.

    The educated user is capible of explicitly disallowing some transformations by use of the keyword "explicit".

    The uneducated user is going to make a mess if he fails to understand and use the feature.

    There is absolutely no ambiguity.

    The fact of the matter is that a poor design will net poor code. Some languages will glop out corrective code for the programmer. Where the programmer is willing to pay this expense, and the application can afford this expense the issue is a giant "don't care".

    Where the cost should not be paid, the "looser" languages don't give the programmer the ability to remove these expenses. To that end these "looser" languages have an intrinsic limit to their functionality.

    Every language does actually.

    However proficency in the tighter (and more demanding) language translates directly into the skillset needed for a looser language. The converse isn't true.

    There is an old aphorisim: "If all you have is a hammer every problem looks like a nail." The secret obverse is "the more tools you have the easier it is to find the right tool for the job."

    Think nailgun. Heavy, dangerous, effective as hell. If you are competent to use one, it will serve you well. If you never learned to use anthing more invasive than wood-glue then don't pelase-god try to use the nailgun.

    The fact that you are uncomfortable using a nailgun doesn't intrinisicly mean the nailgun is poorly designed.

    It's a poor craftsman that blames the tools.

    --
    Innocent people shouldn't be forced to pay for inferior software development.
    --"Code Complete" Microsoft Press