1

General question regarding the STL. Do you guys think that the STL should be used for data structures or would you create custom code? In what scenario would you implement your own code for something that the Standard Library already does? What are your thoughts?

  • One thing to keep in mind which I do not see in the answers as I write this comment is STL does not play well with pre-C++11 smart pointers (which were broken in general due to lack of move semantics prior to C++11). You may find resources that say not to use smart pointers with STL, but such advice is outdated. Go ahead and store your std::unique_ptr and std::shared_ptr in STL containers. (note: std::unique_ptr can be used in STL containers but may need special handling to ensure integrity of the objects stored in the smart pointer.) – user22815 Jul 12 '17 at 16:47
9

I'm not an expert with the STL, but IMO software engineers should always prefer to use mature libraries over writing something themselves unless there are requirement-breaking deficiencies in the library. Even if the library doesn't completely meet requirements, libraries can still be extended and contributed to to meet requirements. The STL has gone through testing, it has been used in production systems for years, and the creators have put a lot of thought into the implementations, so they should be quite efficient.

Unless there is real added value to your project, I do not think you should write custom code for data structures.

6

The short answer is to use STL if at all reasonable. Develop your own code only if you have no reasonable alternative.

In some cases, there are hard and fast rules (usually badly formulated, and poorly reasoned, but enforced anyway) that take the decision out of your hands entirely. If so, that makes things easy.

If you are allowed judgement in the matter, try to use it well. Start by looking at the real goals for your project, what it needs to do, what circumstances it needs to function under, and so on. If you're writing code for a microcontroller that only has (say) a few kilobytes of RAM, chances are pretty good that the STL is not going to be a good fit. No matter how much work it might save, it's just not going to work.

Conversely, if you're developing for a modern reasonably high-end server that might easily have hundreds of gigabytes of RAM (not to mention things like mass storage and such), that changes the equation completely; writing new code to save a kilobyte (or even a megabyte) of executable size is likely to be a mistake much more often than not.

I'd also note that in some cases, the effects change somewhat over time. Just for example, many early implementations of the STL went to some lengths to save memory. One fairly common technique was to split containers into two pieces: a "back end" that work with (for example) pointers to void. Then you'd have a minuscule "front end" that just provided a type-safe interface--for example, it might cast a T * to a void * when storing it, and cast the void * back to T * when retrieving.

This allowed virtually all the code for the collection (or whatever) to be shared between all instances of all types. Instantiating the collection over a new type added virtually no new code (in many cases the casts just changed how the data was viewed so instantiating over a new type didn't increase code size at all).

I wouldn't say such techniques are entirely obsolete today, but implementations intended for desktop or server machines are a lot less likely to use them. For most people, opportunities to (for example) generate more of the code inline to increase speed is more important than saving a little bit of memory. Interestingly, although it's intended as a trade-off of using extra memory to gain speed, I find that this fairly frequently ends up saving memory as well. By allowing more of the code to be generated inline, the compiler is given many more opportunities to optimize the code and (for example) completely eliminate entire swaths of code based on the characteristics of the type actually being stored, where the older methods included (and executed) code to support every possible type, regardless of the type actually being stored.

As with many other areas in software engineering, it largely comes down to a two-step process: start by using your best judgement--but then use real testing; don't trust your judgement too much.

I would caution against taking anybody very seriously if they attempt to oversimplify the situation. People who lack meaningful experience frequently make claims that are quite bold, but lack much backing. Advocates will proclaim that templates "improve execution speed" while detractors will claim they "cause code bloat". While both of these claims (and many others) do have some basis in fact, they're oversimplified to the point of being meaningless at best, and horribly misleading at worst.

3

The one downside of any templates, as are used in the STL, which leads them to banned in several embedded environment is the fact that they generate code based on the types found in your code, this can lead to inadvertent code bloat. If you have a template that takes four input values, all integers, and someone uses it with a float as one of the parameters your object code will suddenly more than double in size.

So if you are working in the embedded world and are required to meet requirements such as MISRA you will find that you are required to avoid all templates, including the STL. So check your coding standards before you start using them.

Going back to the depths of time, to simple name mangling, if you had a function template called Fred with a signature of <T> fred(<T> a, <T> b) and your code was calling int a = fred(1, 2) then your map file would indicate the presence of INT32_fred_INT32_INT32 or something along those lines but if someone added a call, anywhere in your code, to int b = fred(1, 2.) you would gain INT32_fred_INT32_FLOAT and your code would jump up in size - if they then added int b = fred(1., 2.) then INT32_fred_FLOAT_FLOAT would appear. (See Name Mangling on this subject).

  • 2
    @Dimos A template will only be generated when an explicit specialisation of that template is declared. A project with only <int> and <float> std::list will only compile those two typed versions. – Nick Bedford Jul 12 '17 at 6:32
  • 1
    Dimos: C++ templates are essentially a super smart but otherwise glorified find+replace tool. – whatsisname Jul 12 '17 at 6:34
  • 2
    Along that vien, the preprocessor is a dumb but otherwise glorified find+replace tool. Similarly C++ templates can also be though of type-checked macros – whatsisname Jul 12 '17 at 6:47
  • 1
    @SteveBarnes that limitation sounds platform specific. If the debug symbols are accessible, then it can be shown by the debugger. – Caleth Jul 12 '17 at 10:01
  • 1
    There are different embedded worlds. Even 20+ years ago, it was not very rare to see STL with explicit template instantiation running in VxWorks on PowerPC powered boards. – zzz777 Jul 17 '17 at 21:28
2

General question regarding the STL. Do you guys think that the STL should be used for data structures or would you create custom code?

I would always use STL.

In what scenario would you implement your own code for something that the Standard Library already does?

If the implementation of the STL I had access to was severely outdated or buggy to the point of being prohibitive to use, I would consider rolling my own. This should not happen in practice these days, but it used to happen 20 years ago :)

What are your thoughts?

There are places where the STL doesn't cover the necessary functionality; For things the standard library does cover, use the standard library.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.