std/stl is the root to all evil

Started by
165 comments, last by MaulingMonkey 18 years, 1 month ago
Quote:Original post by MaulingMonkey
Quote:Original post by Will F
However, if you want to crush std::vector<bool>, you have my full support. [wink]

Just crush the allowances in the standard for it to behave totally different from any other std::vector< T >.


The standard comittee will do this for you :)

Quote:Discussed at Lillehammer. General agreement that we should deprecate vector<bool> and introduce this functionality under a different name, e.g. bit_vector
Advertisement
Quote:Original post by bpoint
Okay, I just have to stick my neck out on this one... *prepares flame-retardant suit*


If you'll stick your neck out, I'll take a whack. I'll try and keep the flames low, so you end soft-boiled, not hard-boiled. :-)


Quote:
I come from a background of around seven years developing games on consoles where code must be designed for performance and a small memory footprint. This is definitely something STL is not.


Is the overhead of std::vector really that onerous? I guess if you're developing VCS titles... :-)

Quote:
Code must be kept simple, and reasonably easy to understand. I can't look at code that uses STL and figure out what someone is trying to do in just a few minutes because someone overloaded every single C++ operator to mean what he thought it should mean.


What operator overloading in STL? Overloading the brackets "[]" for array access is confusing to you in a map? Last I looked, none of the containers overloaded any of the arithmetic operators. If you're referring to the operator overloading in iostreams, I'd point at that, although part of the standard library, they are not a part of STL.

Quote:
Concatenate strings? That's what strcat is for! (although a good game engine would already have its own cut-down libc implementation anyway)


You rewrite strcat? I wish I had such generous milestone schedules! :-)


Quote:
I look at some of the STL headers and my eyes just glaze over. When I look at a header file, I should see a cleanly laid out function list (or class of some sort) of what a module should do, not some madness that looks like a C++ run-on-sentence. Header files are the second-best documentation, after all.


Here's some source from an STL implementations shipped with a popular compiler:

		// TEMPLATE FUNCTION for_eachtemplate<class _InIt,	class _Fn1> inline	_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)	{	// perform function for each element	_DEBUG_RANGE(_First, _Last);	_DEBUG_POINTER(_Func);	_CHECKED_BASE_TYPE(_InIt) _ChkFirst(_CHECKED_BASE(_First));	_CHECKED_BASE_TYPE(_InIt) _ChkLast(_CHECKED_BASE(_Last));	for (; _ChkFirst != _ChkLast; ++_ChkFirst)		_Func(*_ChkFirst);	return (_Func);	}


Before you complain that I've committed copyright infringement, its fair use to copy small portions of copyrighted material when its used for educational or critical purposes.

Is it really that confusing to you? I guess its a lot of lines for a for loop. Must of the lines are obviously for debugging. I'm all for debugging to help me find errors. Maybe I'm just strange that way. :-)


My opinion is that STL (and boost, and lots of other libraries out there) lead to overly-bloated code. Has anyone who ever _really_ uses STL ever looked at the disassembly of what goes on in there? Blame the CPU because it's too slow? No, no... programmers have gotten lazy and would rather leave the dirty work to someone else rather than build their own routines. Reinventing the wheel? Even so, someone who builds his own routines will _learn_ a lot while doing it. I'm all for it.

Why should I look at every assembly language instruction in my program? I haven't done that since I used to write every line of code in assembly. Even then, I haven't known every single instruction run since I've had to deal with OS calls since the 16-bit days.

Do you not make operating system calls in order to know exactly what's going on? Do you write your own file I/O routines that directly tap hardware?

Although I'm not a firm believer in the "we can do it slow for now and optimize it at the end", STL fits that paradigm. I don't know anybody who has used it complain that it ended up being something they needed to optimize out. Even if it ends up being something you do need to speed up, with its well-developed concepts, you can always write your own specialized container if it becomes necessary. As long as you model the concepts, it's an easy drop-in.

Quote:
And once you've built your own routines, they'll most likely be better than STL because _you_ designed it for _yourself_, and that leads to the most amount of code reusability in my book.


That's a categorically false assertion. If the author(s) of the code know more about the topic than I do, they'll almost certainly write better code. If I write a sorting routine based on a bubble sort, I've almost certainly erred in not using the quicksort available in the STL. When I look at what Stepanov has designed, I'm quite impressed. I'm willing to bet its more reusable than what you've written. I'm not trying to insult you. It's more reusable than anything I've written. I'm sure there's plenty of STL users who agree with that position.
I know I should resist, but I have no willpower.

This post is not intended to be a personal flame against you, but rather a argument for the fact that your current opinion of the STL and code reuse in general is based on knowledge that may have been valid seven years ago, but certainly is not now.

Quote:
I come from a background of around seven years developing games on consoles where code must be designed for performance and a small memory footprint. This is definitely something STL is not. Code must be kept simple, and reasonably easy to understand.


The STL is quite efficient in the general case, and provides a means (such as custom allocators) for you to tailor its behavior to your needs. One of the benefits of the STL is that it is standard, and thus commonly understood (except by naysayerswho refuse to learn it or embrace it based on "facts" that are out of date). Not having to re-learn the ins and outs of somebody's custom container library for every new project drastically increases ones productivity.

If, in a specific situation, you've determined that a given (properly used) STL container is the bottleneck in a (properly designed) algorithim, and you've exhausted all the possible steps for customizing the behavior the STL in that case, then you have suitable grounds for considering a custom implementation. Until then, you are probably just making more work for yourself and for new programmers who need to learn your codebase.

Quote:
I can't look at code that uses STL and figure out what someone is trying to do in just a few minutes because someone overloaded every single C++ operator to mean what he thought it should mean. Concatenate strings? That's what strcat is for!


Are you sure you are reading STL code and not boost::spirit code? The STL doesn't really have any over-the-top overloads of any operators (other than maybe the bitshift operator overloads for streams). This statement just reveals your limited C and/or C++ centered thinking: most other languages provide an overload of operator+ for string concatenation natively. I don't see this as a particularly counter-intuitive use of operator+, either.

The STL is not particularly complicated, and it's well documented. If you can't understand what somebody's intent is in a given piece of STL-heavy code, that probably just means you don't have enough exposure or experience to those aspects of the STL.

And please don't tell me you are advocating the use of C-style strings and strcat and its kin in favor of std::string (when writing C++ code). That's just masochistic and smacks of "not-built-here" syndrome.

Quote:
My opinion is that STL (and boost, and lots of other libraries out there) lead to overly-bloated code. Has anyone who ever _really_ uses STL ever looked at the disassembly of what goes on in there?

Many people have, including myself, and I was not shocked by anything I found. Modern compilers are very good at avoiding code bloat due to template usage.

Quote:
No, no... programmers have gotten lazy and would rather leave the dirty work to someone else rather than build their own routines. Reinventing the wheel? Even so, someone who builds his own routines will _learn_ a lot while doing it. I'm all for it. And once you've built your own routines, they'll most likely be better than STL because _you_ designed it for _yourself_, and that leads to the most amount of code reusability in my book.


This is just crazy. Re-inventing the wheel for non-educational purposes is a waste of time and money. Re-inventing the wheel in production code is just asking for more bug reports and less happy users. Assuming that something you have written is better only because you wrote it is naive and arrogant.

These are exactly the ideological beliefs that plague the game development industry - "not built here," "performance above all else," and in general being locked into a single worldview and refusing to accept change (N) until the rest of the world has already accepted change (N + 2).

Learn to love the STL. Hell, learn to love a language other than C++, too - maybe even a crazy non-imperative one! You will be amazed at the time and effort you save.
Quote:Original post by bpoint
Okay, I just have to stick my neck out on this one... *prepares flame-retardant suit*

I _fully_ agree with the OP. STL is horrid, it's ugly... it's like a red-headed step-child. :)


It has it's problems. Think you can do better?

Quote:I come from a background of around seven years developing games on consoles where code must be designed for performance and a small memory footprint. This is definitely something STL is not.


You're right. Instead, the STL is flexible - so you can pass in a custom allocator for a small memory footprint, or make a tradeoff there for allocation performance speed. You get to decide instead of being forced into a single implementation scheme - I fail to see how that's a bad thing.

Quote:Code must be kept simple, and reasonably easy to understand. I can't look at code that uses STL and figure out what someone is trying to do in just a few minutes because someone overloaded every single C++ operator to mean what he thought it should mean. Concatenate strings? That's what strcat is for!


Yeah - because we should really be using a function that deals with arbitrary buffers of totally unknown size that will end up overwriting random bits of memory should our buffer be to slow. You want verbose? Use std::string::append. You're not forced to use the operators. Of course, the fact that most people tend to choose to use the operators tends to hint that they are in fact rather easy to recall, and fairly intuitive.

Quote:I look at some of the STL headers and my eyes just glaze over. When I look at a header file, I should see a cleanly laid out function list (or class of some sort) of what a module should do, not some madness that looks like a C++ run-on-sentence. Header files are the second-best documentation, after all.


So now we're attacking the STL implementors intead of the STL itself. I'll admit they don't write the cleanest of code. But you know what? Headers are only the second-best. I'd suggest you'd use the first-best - in this case, Traditional Documentation.

Quote:My opinion is that STL (and boost, and lots of other libraries out there) lead to overly-bloated code. Has anyone who ever _really_ uses STL ever looked at the disassembly of what goes on in there?


Yes.

Quote:Blame the CPU because it's too slow?


No, because usually if the compiler isn't ancient, it's not.

Quote:No, no... programmers have gotten lazy and would rather leave the dirty work to someone else rather than build their own routines.


Yeah. You're right here - I'd rather let the writers of the bloody compiler, who know what optimizations their specific compiler does and does not do, and which hand-coded ones it can take advantage of, write code specifically tailored to get the best performance in that environment, than attempt to do this myself for N different platforms at the same time.

Quote:Reinventing the wheel? Even so, someone who builds his own routines will _learn_ a lot while doing it.


Eventually. But it will hardly be the most efficient way.

Quote:I'm all for it. And once you've built your own routines, they'll most likely be better than STL because _you_ designed it for _yourself_, and that leads to the most amount of code reusability in my book.


Entirely disagree, unless you plan on coding in a cave all by your lonesome until the end of your days. The moment you step outside the sheltered life of code focused for nobody but you, suddenly, other people will need to interact with your code. Would you rather interact with it using the STL, or would you rather be forced to learn yet another person's container set which is completely incompatible with the containers used in this other module you wanted to use to do most of your work? Suddenly, your quest to reinvent the wheel leaves you with a triangle, a hexagon, and a tank tread. Now build me a racecar with them. The deadline is tomorrow.

At least if you had two tank treads, you'd have a base with which you could test out the engine. As is, you'll be forced to start making new wheels, just to test out the rest. This is most likely a waste of effort if you don't know what kind of terrain this race is going to be over...
I have a few things to say about it.
First of all, if you don't like the syntax, then write a wrapper class.
You should write a wrapper class anyway, because if you want to change the implemntation of your data objects, you could do it more easly this way.
However, I myself dont use std much. I don't see what is the problem to write a linked list?
You can make all kind of special variations to the list which std won't give you.
Plus, you write it once and you can use it for all the following projects.
I assume that if I will need to use something more complex like a binary tree with flips, I don't remember whats the name. Then I would probabbly write a wrapper calss and in the implementation I will use something like std.
The only thing I used from std was string I believe, and maybe also stringstream and such.
It's all about the wheel.Never blindly trust technoligy.I love my internal organs.Real men don't shower.Quote:Original post by Toolmaker Quote:Original post by The C modest godHow is my improoved signature?It sucks, just like you.
Quote:
I don't see what is the problem to write a linked list?

Because yours will probably be less efficient, more buggy, and require other people who interact with your code to learn the ins and outs of your implementation, which is probably not as well documentated as std::list.

Quote:
You can make all kind of special variations to the list which std won't give you.


Such as?
Quote:I come from a background of around seven years developing games on consoles where code must be designed for performance and a small memory footprint. This is definitely something STL is not.


Well, that's one way of looking at it. Another way of looking at it is that STL code is either performant, or small in memory, or in some cases both. I have only ever seen a few people actually profiled their hand-rolled code against the STL, and I've never seen any significant performance boost. On the other hand I have seen many bugs and errors, which you just don't get in the STL.

We're quite happy to use STL in our console games and it does the job just nicely, thanks.

Quote:Code must be kept simple, and reasonably easy to understand.


Anyone with sufficient experience in C++ can look at STL code and know exactly what it does, because it's used everywhere. Your hand-rolled code that your company uses? Yeah, YOU know it, but when you hire someone new and they write something like linkedListAdd and you have to explain that no, they really needed to use linkedListAddToEnd, and there's casts of void*'s everywhere... is that really easier to understand?

Quote:Concatenate strings? That's what strcat is for!


I really hope you're not using strcat for something as important as a console game, which is emphatically not allowed to crash! strncat maybe, strcat_s quite possibly, but please god not strcat in anything critical! I put it to you, it is both faster and more secure to write this:

DoSomethingToFile( folder + "\\" + filename );    // using a string


...than it is to write this...

char path[MAX_PATH];strncpy( path, folder, MAX_PATH - 1 );strncat( path, "\\", MAX_PATH - 1 );strncat( path, filename, MAX_PATH - 1 );DoSomethingToFile( path );    // using a char*


...particularly remembering all the -1's which I nearly did myself before subnmitting.

(Alright, it's still not 100% secure as written. If folder or filename are sufficiently large, the string might fail to resize, and the program will crash - and I'm not checking for exceptions (apart from anything else the overhead of exceptions precludes their use in most games). However, this is substantially LESS likely than a buffer overflow of a mere 260 characters. Furthermore, if the worst comes to the worst, I will know if the string memory allocation fails because it will crash instantly, which hopefully will happen during QA rather than after release (checking player input for validity is therefore still necessary, of course). If str(n)cat writes off the end of a buffer, there are no clues, just strange behaviour and possibly crashes in a completely unrelated part of the program. Good luck hunting THAT down during crunch - yeah, I've been there, and didn't enjoy it.)
STL, oh my STL..
Someone said that we should rewrite STL in our projects.
I tend to reinvent the wheel to learn.
I always do that.
But I never did use a list except std::list.. It is not ever that I actually create a linked list to actually use it, but to learn.

In short, if you want to learn, reinvent then put into garbage. Use what the professionals have already created.
[ my blog ]
Wow, this is getting into another round of pointless C++ vs. C flameage.

Maybe we can take a step back and look at it like this. I understand bpoint as saying STL is not good in all cases (viz. time-critical code); everyone is jumping on him as if he'd said "it should never be used and ideally banned from existence". Is the former interpretation so hard to accept?

Quote:And please don't tell me you are advocating the use of C-style strings and strcat and its kin in favor of std::string (when writing C++ code). That's just masochistic and smacks of "not-built-here" syndrome.

There can be very valid reasons to do. When working under constraint that NO locks must be taken, std::string won't cut it. Yes, could use allocator that basically doles out a PATH_MAX-char buffer, but IMO strcpy_s is simpler in this case.

Quote:
Quote:Blame the CPU because it's too slow?

No, because usually if the compiler isn't ancient, it's not.

Then the challenge in your field of work is obviously not optimization. Which is fine, but not to say there is no need to do so.

Quote:
Quote:You can make all kind of special variations to the list which std won't give you.

Such as?

Such as reducing memory overhead from (4+4)*num_objects to log2(max_objects)*num_objects. In certain applications, a doubly-linked list can be had with one pointer (by storing prev XOR next); the pointer can be reduced to a few bits if allocator guarantees all nodes are consecutive.
E8 17 00 42 CE DC D2 DC E4 EA C4 40 CA DA C2 D8 CC 40 CA D0 E8 40E0 CA CA 96 5B B0 16 50 D7 D4 02 B2 02 86 E2 CD 21 58 48 79 F2 C3
Yes, errors spawned by C++ templates [and by extension the Standard Library] are lengthy, and fairly unaesthetic. That's the price you pay for their use, and interpretting them does get easier.

If you're not making use of C++ templates, I would question your choice of development languages. Template goodness is one of the few advantages C++ still holds over newer rivals.

This topic is closed to new replies.

Advertisement