C++ and the STL 12 Years Later: What Do You Think Now?
profBill (98315) writes "Way back in 2002, Slashdot ran a story asking what people thought about C++ and the STL. Well, it's 2014 and C++11 is well out there with C++14 on its way.
I teach a second programming course in C++ with a heavy emphasis on the STL (containers and generic algorithms). I just wondered what people think about the situation today. Personally, I think C++11 has cleaned up a lot of problems, making it easier to use, but given all those who work with C++ for a living, I wondered what they thought today compared to then. Are people using C++11? Does it matter at all? I'd love to share the responses with my students! They are always curious about what practitioners are doing these days."
I teach a second programming course in C++ with a heavy emphasis on the STL (containers and generic algorithms). I just wondered what people think about the situation today. Personally, I think C++11 has cleaned up a lot of problems, making it easier to use, but given all those who work with C++ for a living, I wondered what they thought today compared to then. Are people using C++11? Does it matter at all? I'd love to share the responses with my students! They are always curious about what practitioners are doing these days."
This will probably come off as a troll, but it's really not intended to be. And keep in mind this is just my experience in my domain with the type of projects I've worked with. There's lots of different domains/projects sets where this wouldn't apply.
I used to love c++ and berade people who used wimp languages like Java. These days I mainly use java, and when I do have to use c++, it feels painfully dated.
At to C++11, while it added some useful stuff, in general it feels like it's just flailing while trying to bring in some of the language features of newer/more modern languages. The new concurrency stuff in particular is just plain unseemly.
Also, a relatively minor but annoying and long-standing problem with doing anything non-trivial in c++ is the lack of consistency between 3rd party libraries. Java has spoiled me into expecting everything to adhere to one convention, but with a c++ project as soon as you've got more than a few external libraries, you end up with a huge mess of code that doesn't mix properly, and writing adapters for everything to get that consistency is just insane.
Long rant short: I'm finding myself using c++ now mainly for:
- small bits of functionality to be used via JNI
- small stuff mainly focused around one library/task (Qt, pqxx, whatever)
Doing anything large and complex with c++ these days just doesn't appeal to me any more. I can build it much faster with java, it'll be more maintainable, and performance wise it's fine for what I do.
Also: floating bottom popup ads.. really dice? You just fell off one mans adblock whitelist.
Totally biased, non-specific: Having written more than 1M lines of C++ in the late 80's early 90's, back when I'd have killed for an STL, I think every iteration adds real improvements without generating divisions amongst professional developers (unlike iterations of Java).
Who can't nowadays? Embedded ARM SoCs come with GB's of RAM, and plenty of compute horsepower.
Unless you are bit twiddling on an AVR, or other micro, why not?
There are applications where no overhead is always better than any overhead. Mostly stuff involving the simulation of physical processes. For example in computer sound synthesis and processing no matter how much computational power you throw at me I will use it up. A musician buys a computer twice as fast as the previous one? Great now he can use 10 convolution based reverbs instead of 5 or use that new virtual analog synthesizer plugin that emulates each transistor of some old korg synth perfectly and he will and his computer will choke just as before. Peoples needs are different. Just because you can't think of uses for extra CPU cycles does not mean other people can't and if your program wastes those cycles people will buy from someone else.
I've used it off and on since "c with classes", and while it's regularly improved at the detail level, it's still
- non-orthogonal
- complex
- exceedingly subtle in spots.
I think the best characterization is still Ozan's:
davecb@spamcop.net
I haven't worked with C++ much for about 3 years, but when I did, manually editing Makefiles and the like caused more than a little indigestion. After having worked with Python, JavaScript with Grunt, several IDEs, and even crap like Maven for Java/Scala projects, I don't want to go back to the early steps of getting C++ projects just to execute. There seems to be no doubt that I've missed some developments in that area in the last few years, though.
I don't know anyone who worries about garbage collection in C++11.
The STL does one thing very well: it's very predictable performance-wise while being reasonably useable.
When you use it, you know perfectly what the performance is going to be.
It also offers some occasionally-useful features (std::weak_ptr for instance). c++11's move constructors and rvalue references are very good for squeezing out the last bit of performance where possible and for ensuring exception safety to certain operations; although it's mostly useful for very low-level, entrenched libraries such as the STL. Lambdas are syntactic sugar, but a well flavored one.
c++ is now a very different beast than it was in the 90s. If used properly, it can be very effective (performance-wise) in complex projects. But it can also give programmers tons of rope to hang themselves with.
I don't know anyone who worries about garbage collection in C++11.
Quite. The OS cleans it all up after the application exits, anyway.
Stick Men
We use C++ exclusively for academic projects but we rarely use STL for performance reason. Some of the C++11 functions really come to rescue like number to string conversion, time keeping etc that may save a day but in general we use "templates" almost everywhere but use of STL is limited to some once in a while operations like loading data from an input file.
The C++ standard library is probably the highest quality standard library of any language I've seen.
It is documented down to an very low level. I can't count the number of time I've been using some .NET library only to find out that it has some undocumented requirement, quirk, or wildly unexpected time complexity. You never get things like that in the C++ standard library -- assuming you've read the documentation thoroughly, you should never be surprised.
The standard library takes full advantage of the language, and it's as lean as ever with the "don't pay for what you don't use" mantra generally remaining in full effect.
A downside? I may be able to develop something that uses a tenth the RAM and half the CPU in C++, but despite the strengths mentioned above, it's going to take me at least twice as long and I'm going to need to juggle a number of inconsistent 3rd party libraries -- no doubt some of them being plain C so I'll need to make some RAII wrappers, etc. -- it remains incredibly low-level.
Boost picks up some of the slack, but C++ really needs more of the things commonly used today. Things like HTTP, XML, web services, SQL, configuration, and cryptography should be built in, but they're only just now looking at a simple sockets library. This is a huge weakness. C++ is used in a lot of low-level situations so I don't know if these should be part of the standard library proper, but at the minimum an additional "framework" standard that implements high-level stuff for the more common unconstrained users would be immensely useful.
The language itself is very strong, and C++14 cements even more useful things into it. The only things I wish they'd add is LINQ and async functionality similar to C#.
They added far too many features to the language in order to please everyone. Why? People who need high level languages have plenty of others to choose from.
Personally I got sick of it and its never ending increase in complexity and just stick with a sort of C with classes and the occasional use of the STL and thats it. In fact sometimes I'll just use plain C. If I need a language with really high level constructs then thats what Python was invented for.
Unlike a lot of commenters here, I actually use C++ every day, and have been for about 20 years. I think the evolution of the language has been great.
I write software for the digital visual effects industry, and it has to be fast, portable, and adaptable. To that end I tend to write as light-weight low-level code as possible, strongly separated from the UI, since I never know where I may end up needing to use it. For instance, when we decided to put a bunch of our filters on iOS, it pretty much worked as-is.
One key to writing nice clean portable code is to avoid dragging in too many dependencies. At the lowest level, about the only external dependencies I used are a few things from boost. But with C++11, a lot of that functionality has moved into the core language (or the standard library). Threading and synchronization primitives such as atomic_int, thread, and mutex are now part of the language, and no longer need to be brought in from boost. This makes everything much cleaner, especially with build/test integration.
lambdas are another thing I really like. Instead of writing messy functors (for auto-threading image processing kernels for example) I can drop the code in-line using a lambda. Much more readable and cuts down on complexity.
The new move-semantics have also made nice improvements to code design and performance, allowing you to move whole objects around with practically zero cost as if they were references.
On the UI side of things I usually use Qt, and there have been C++11-related improvements there as well, such as signals and slots now being type-safe.
D *is* neat.
The only problem is lack of momentum.
It was Bjarne himself who said that there are two kinds of programming languages: those everyone complains about, and those that nobody uses.
On-topic, lots of people are going to hate C++, for its multi-paradigm "everything and the kitchen sink" approach combined with near-C-compatibility and low-levelness. It's the kind of language where two programmers come up with five different ways to do the same thing, and four of them are probably wrong in non-obvious ways. It's fun though, in the way that a high-performance sports car is fun to drive, but easy to wipe out.
I've been using it professionally for 15 years now, and if I observe anything, it's that the longer I use it, the more my stuff looks like C. I keep shaking my head at younger colleagues mis-using templates all over the place ("re-usability!", and hour-long compile times, coupled with really non-obvious implicit conversions and instantiations, never mind the error messages), and object-oriented hierarchies where each object is such a tiny part of the system that you need to remember 10 classes at the same time just to have a slight inkling of what this thing is actually supposed to do.
I still have that nearly irresistible urge to defend the language whenever discussions like these come up, but so much of that is because it's the language I use all bloody day. And then I write something incredibly useful in 10 lines of Python.....
C++ has its place, a masochistic place, ostensibly programming a higher-level abstraction than the people writing plain C ("troglodytes!", but most of them actually seem to know what they are doing and rustle up the higher-level abstractions directly in C, I have respect for you guys), and the people who don't have that much need for low-level features, the last drops of performance or cross-platform compilation (you're probably working in Java, C#, Python, Ruby, and *enjoying it* most of the time. And yes, you Java guys have every right to tear into me about cross-platformness, it's not like it's just hand-waving in C++ either). It's sort of a similar niche to PHP I guess. You know full well that a lot of the reasons for the hate are true, but all you have is this swiss-army-knife of a hammer and everything must be a nail.
Over the course of 10 years that would be about 270 lines a day 7 days a week, 52 weeks a year. Including debugging an testing? I don't think so my friend.
Languages that aren't designed top to bottom at the beginning tend to evolve into Frankensteins. Perl, C++ have evolved in accordance with fantastically clever ideas, but end up being more complex than anyone wants to deal with, and a mess of syntax. Java is heading that way too. The question is can anyone put all this cleverness into something simple? Say what you want about things like lisp and scheme, they managed to put incredibly powerful ideas into something that is at its core simple. If only other language designers achieved it too.
The reusability and modularity of C and C++ has always been poor, and, though improved, still is. C is good for making your own linked list functions, not so good for using libraries containing those functions. We've persevered in spite of that, and created hundreds of libraries in C. But it's still a mess.
The STL is fine as far as it goes, but, for example, it simply cannot integrate something like Perl's hashing abilities and regular expressions as well as Perl itself. The programmer can sort of approach the cleanliness of the Perl syntax by making clever use of C++'s operator overloading, but among the problems with that is that there are a small number of operators available for overloading. The programmer cannot create new operators. Better to retreat to the messy function call syntax. That is, instead of something like c=a+b; it's c=add(a,b);
And the function call syntax has its own limitations. Unless the coders include the library for variable numbers of parameters (printf being the go to example of such a function), they're stuck with fixed numbers of parameters. Having to do prototyping is another annoyance. Surely computers have progressed to the point that it is not a huge imposition to ask a compiler to make 2 passes through the source code, or store the data types of the parameters of a call to an as yet unknown function, to resolve forward references itself instead of burdening the programmers with that chore? But even if those 2 limitations are addressed, calls are still like having to do math with prefix notation and still be forced to use parentheses everywhere even when the number of parameters are fixed, rather than a choice of prefix, infix, or postfix notation with some operator precedence so that it isn't necessary to surround absolutely everything with parentheses. In that respect, C is no advance at all over Lots of Irritating Superfluous Parentheses.
Another resuability problem was name collision between different libraries. Two libraries with a "sort" function, for instance. To deal with this, it became the custom to prepend the library name to every function name. Now we have namespaces.
Intellectual Property is a monopolistic, selfish, and defective concept. It is "tyranny over the mind of man"
In production software you don't always have the luxury of being able to switch to the latest and greatest in an instant.
In the case of C++(and others) as things change you have to update compilers, this often(read: always) means stricter requirements as the compilers improve (IOW: Newer compilers catch potential problems in your code better than older ones, and moan about it more). When you have a system of millions of lines of C++, this means you have to dedicate manpower (which you probably need somewhere else) to fixing all these "new" issues before you can upgrade all your compilers. This is good, but you can't always dedicate 100% of your time to it. Aside: For our stuff we turn warnings-as-errors on always, which maybe makes this task more difficult than it is for others, but we get to catch bad code a lot quicker.
My team only recently got to the point where all our stuff was in a state that we could start using the newer compilers and hence, standard. But we've been chomping at the bit to use C++11 for a long time. So yes, I do care. And yes, I think it's much better now.
Why do we care?
For one, lambda's make our lives, and code readability, SO much better. Especially when using the std algorithms.
We will definitely be utilising variadic templates in our shop as we tend to be template meta-programming heavy. We avoid re-work like a plague.
Personally I'm glad to see the new initialiser lists because we also stress TDD and nothing sucks more than not being able to set up test data easily and have it be readable. Almost always requires some instrumentation first.
> no, yes, maybe (tagging beta)
I assume what GP means is std::unique_ptr, std::shared_ptr, std::make_shared, and then your own custom make_unique because they forgot that in the standard and a bunch of std::moves to convert the canonical unique_ptr from your factory functions into the shared_ptrs that you are actually using everywhere else.
;-). Seriously though, the language has made strides with C++11 and C++14, but it will always remain a minefield of ways to stab, shoot, detonate, incinerate and irradiate yourself in the foot, with some implicit casting to hands and other appendages thrown in.
And then fighting with the several iterations of only half-done C++11 implementations in recent versions MSVC compared to the better support in Clang while trying to keep your code compiling across 4 different platforms with as little use of #ifdefs as possible. May the noodley-appendaged one help you if you were hoping for easy multi-threading or unicode support.
I keep telling myself I like this language, but who am I kidding
I have been working with C++ (as well as Java, C# and other languages) for several projects over the past 13 years. Since C++ is still the main language for the projects I'm paid to work on, I find the improvements to the STL useful every day in avoiding doing custom things. We used to have our own class similar to std::shared_ptr and std::unique_ptr, which we have since replaced with the standard. With std::bind() we have reduced the complexity of many of our functions. As another commenter said, the lambda functions are great. I'm not sure why there is so much hate for C++. Having worked with both C# and Java on several projects, I still think our C++ projects have the cleanest code and have the best performance before tweaking. I am one of the few developers that bounces back and forth between languages so I don't think it is a case of C++ people trying to write C# or Java, the people writing C# and Java are developers who write those only.
We just migrated our codebase from C++ STL to C++11 and in general, it was worth the pain.
The main benefits for us were better awareness of modern character encoding - but stuff like lamda functions are pretty cool too, and we could probably tidy up a lot of our earlier code to use more C++11 features.
I was brought up on Assembler (Z80, 680x0) and moved to 'C', and then migrated to 'C++', so my early C++ was very C-like (not unusual). However, I've not looked back. I know that you are asking about C++11, but C++ itself is probably worth highlighting.
I also know Java, Obj-C, (and a bunch of other languages that I have used in less commercially sensitive contexts) and there's a lot to be said for them too. But when I feel like getting close to the metal, it's C++ for me. I guess it's b/c one can still (just about) follow the assembler generated by it.
But then I'm old in my approach. Modern optimising compilers, with coding strategies, static analysis (as well as excellent IDEs) probably have more effect on my productivity than any language sub-variant.
This comment was written with the intention to opt out of advertising.
I love templates when used in things like vectors, maps, sets, etc. Then combined with the new for loop iteration in C++11 it is great.
But the nightmare is that many people are putting templates into everything so as to accommodate "future" flexibility. But the simple reality is that unless you are programming a hard core library it is a disaster to program flexibility when it is not needed. The end result is code that might score well on a templates test, but will be basically unreadable or alterable by any normal human.
So there seem to be templates as used by programmers and templates as used by showoffs.
I work as a software engineer for a major software company. We do not use C++11, and likely won't start for years. Due to the existing code base, changing up tools is a costly and dangerous thing to do and it is never done unless absolutely necessary.
STL is something of an abomination. Good intentions, and we do use some of it, VERY sparingly, but generally speaking it makes code more difficult to understand and maintain.
I'm sure that was said more or less as a joke, but it rubs me the wrong way. The basic suggestion here is that no language that reaches sufficient usage is going to be without its problems. That's fair, but I'm reading from it an implication that the criticism is purely due to its popularity, and that's not fair. There are a lot of problems with C++; some are fixable, some are too inherent in the design to be fixed. A lot of what could be fixed has been, and that's fantastic, but there's still plenty of room for legitimate criticism that has nothing to do with hating what's popular.
Regarding languages that "nobody uses," that doesn't necessarily say anything about their quality; some things just don't take off for whatever confluence of reasons. It remains to be seen whether D specifically will or will not, but from what I understand, it is very well-designed and avoids a lot of the design issues present in C++. That's really cool if true and I'm looking forward to seeing if those claims hold up.
From Page 3 of this:
The C++ STL, with its dyslexia-inducing syntax blizzard of colons and angle brackets, guarantees that if you try to declare any reasonable data structure, your first seven attempts will result
in compiler errors of Wagnerian fierceness:
Best Slashdot Co
Staying with rudimentary C/C++ gives you cross-platform compatibility. And it may come as a surprise, but there are still a lot of legacy systems out there that don't have the latest and greatest C++ libs. As for map libraries, you think those didn't exist before STL?
When all else fails, run.
It's better than any of the alternatives?
C++ is to C as Lung Cancer is to Lung.
Trolling is a art,
The library size for one.
Most of the STL is in headers. If that's causing problems with library bloat, you need to find a better vendor. Specifically what is too heavy? I doubt using std::push_heap on a statically allocated array would be smaller than if you wrote some heap code yourself.
I do not see why anyone is getting upset over my comment.
We're not upset, just skeptical. The reason being is that the arduino environment runs C++ happily, and you can pick and choose things out of the STL effectively. There's plenty in there that will run on raw arrays, and I'd be surprised if it generated more code than a by-hand implentation.
SJW n. One who posts facts.
C: "Here's a gun. Don't shoot yourself in the foot."
C++: "I see you've been shooting yourself in the foot! Well, here's a different gun, rather like your old one, only we've added a safety and a trigger guard and oh by the way it now shoots 40 caliber shells containing fission-warheads."
Python: "Have a wiffle bat."
When was the last time you ran anywhere? I mean with your own legs, not by pressing 'X'?
Case in point: I compiled hello world using for a Game Boy Advance. After I added -Wl,-gc-sections to remove unreachable code, it still took 180,032 bytes out of the system's 262,144 byte main RAM. Much of this space was dedicated to libstdc++ bringing in the libraries for "locale" (date, time, and money) support, even if a "locale" sensitive object never gets printed.
#define if(x) if ((x) && (rand() < RAND_MAX * 0.9999))
#define true ((__LINE__&131)!=131)
#define InterlockedAdd(x,y) (*x+=y)
Yeah, C does give you the tools to turn debugging your program into a living hell. ;) With great power comes great responsibility.
When was the last time you ran anywhere? I mean with your own legs, not by pressing 'X'?
"auto" is there to reduce the typing -- that is all. Instead of writing MyContainer::const_iterator::value_type x = ... I can write auto x = ... because the compiler can deduce the correct type. It is not "too complex".
It is a convenience, like a "for loop" with a built-in iterator is there because requiring the programmer to write the boiler-plate required for a "for loop" with "do/while" is stupid. Your headline might as well read "C admits it is too complex with for() loop construct."
And C# is not collapsing under its own weight. Any programmer, no matter what language they program in, that is not using a modern, intelligent IDE is wasting time and money -- they are a hack (in the worst sense of the word) and not a professional.
the growth in cynicism and rebellion has not been without cause
I would fire coders using naked pointers.
I think this really reflects the flexibility of C++. You can write bare metal code and you can write high level application code ini the same language. There are so many situations where naked pointers are superior to smart pointers and the other way around, and if you get the two camps in the same room there is a good chance they will kill each other trying to convince the other side that their way is the one true way.
Good news for you: size() is now O(1) in C++11.
SJW n. One who posts facts.
JavaScript: "here, let's point your gun at the customers instead".
People like you are the reason that there's so many bugs in software these days and code is so hard to maintain.
From a less tongue-in-cheek standpoint, optimization (beyond choosing the proper data structures/algorithms and the like and thinking about where bottlenecks might occur as you go) should only be done in the following manner:
1) Run the program and assess the need. If there is no need, STOP.
2) Instrument the code and find out what is *actually* using up your CPU time.
3) Improve the code in the sections that yield the most benefit; go back to #1.
People who try to optimize everything as they go along spend most of their time "optimizing" things that have no perceptible benefit and are far more likely to simply obfuscate the code and introduce bugs. You need to assess need and find out where it matters first. Is it really worth it, for example, to optimize some string comparison that runs maybe five times in your typical program execution? NO. Is such an "optimization" a likely place to find bugs, including potentially serious ones? You betcha.
As a side note, I find most people who obsess over optimization without profiling spend most of their time doing "optimizations" that don't help at all or are often even counterproductive, such as macro bitswap tricks, math-approximation functions, manual loop unrolling, etc, just assuming that they help, rather than things that actually help, found via testing.
When was the last time you ran anywhere? I mean with your own legs, not by pressing 'X'?
Alternately, you use shared_ptr to express shared ownership, unique_ptr to express sole ownership, and raw pointers to express that the pointer doesn't own the memory in any way. That can work.
"When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes