62 comments

[ 3.5 ms ] story [ 130 ms ] thread
C++ is very much a mixed bag but the new features in the C++11 standard do help a lot. The "auto" keyword and range-based for loops alone have decluttered my code quite a bit.

The new smart pointers make me nervous after the auto_ptr fiasco but they seem to be working fine in my code so far.

I'm looking forward to trying out the lambdas as soon as they hit in XCode.

The BOOST_FOREACH has helped declutter my code a lot as well. After getting used to it, I feel it expresses intent better than a for loop with auto begin-end.
Is there a resource somewhere listing which compilers support which features of C++11? Or do all major compilers already support the new standard?

Portability is probably the main reason I'm concerned about switching my codebase to the new standard...

(comment deleted)
Pretty much everything in C++11 sounds extremely cool and useful. It seems like the committee did their homework; from what I can see all of the new features are well-designed and thought through. Lots of things that were verbose or inefficient before are fixed, and as a result the language will be more expressive.

But I just have this nagging worry that C++ is going to collapse under its own weight. C++ was already the most complicated language in common use IMO (except possibly Perl); with C++11 there are more keywords, more constructs, more variations. I just hope this doesn't make C++ seem totally unapproachable to beginners, or too hard to keep up with for people who are already using it.

C++ isn't going away but its domain continues to contract. The C++11 standard will slow the erosion but I'm very doubtful that we'll see the "C++ renaissance" that people like Herb Sutter are predicting.

Even now on low-powered devices like phones you can often get away with more wasteful languages like Java or even Javascript. And server-side there are a bunch of much higher-level languages that are close enough in performance and usually with a far richer ecosystem to boot.

I used to think like that, but now I am back to languages with native code generation for the projects where I can dictate a language choice. Depending on the project requirements, this means C++, D, Go, Haskell or OCaml.

Sadly from all options I listed above, C++ is still the best one supported in the industry. But coupled with a good static analyzer, it is quite nice.

What we miss is the possibility to have native code generation support for higher level languages to become more widespread.

I'd be curious to know why you switched back to languages with native code generation? Is it mostly due to the control you have over code performance? Is so, are such applications fairly specific in scope, e.g., fluid-simulation on the GPU?
More control over performance and easiness of distribution.

Desktop applications, where a good integration with the operating system is required.

System programming and distributed systems as well.

I lost a bit faith on VM based systems for deployment, due to too many deployments gone wrong.

Now I advocate systems where you can get the best of both worlds. A VM based environment for development, and compile to native code when releasing the product.

Something like Eiffel, ML and Lisp language families already offer.

Java and .NET also have such options available, but they are not widespread.

Raw pointers, manual memory management, and "what you see is roughly what's executed in assembly" is very helpful for a wide variety of performance sensitive tasks, there is a whole world out there beyond CRUD apps. There are many trivial optimizations you can't do without writing native code. Writing any performance sensitive code in a high level language is like playing the telephone game.

What's funny is that high-level languages develop a culture of not caring about performance, which makes what could be a mild problem, much much worse.

Java is actually a pretty fast language(for most purposes), you wouldn't know it from 9 out of 10 desktop java applications I've used.

I'm fond of native languages too and would like to believe that they're making a comeback but I really just don't see much evidence for this so far.

I've dabbled in OCaml and Haskell but my current favorite is Go. I'm still looking for a good excuse to use it.

The design idea of "don't pay for what you don't use" seems to cause the language features/library to be wide and orthogonal instead of deep; the weight is more or less spread out. Beginners can learn in increments, which is the approach I took for C++11 - first I used new template features, then rvalue references, then threading, and so on.
I'd have liked better ptr features. The auto-cleanup is good. Is it flexible enough to do other things like: auto-close (a file ptr); auto-deref (a ref-counted thing); auto-unlock (a critical section) etc?
All of these can be done in a class's destructor, which is called when the object is deleted, e.g. when a shared_ptr's ref-count reaches 0 (i.e. there are no references to it left). To express observation (and break cycles) there is weak_ptr, and to express ownership there is unique_ptr.

IMO the new pointer stuff is excellent, and relieves the large majority of the memory management burden.

There are some boost macros which will run clean up code at the end of the scope if you prefer. They are not pretty. But they work. (This is a life saver in a long function with multiple exit points)
3 questions before moving to C++11

- which architectures is the author discussing when he talks about performance gains, what are the ISA requirements and numbers?

- what compilers are supporting it?

- why is it good to have "magic" happening in the background? E.g. reason 4 is not something I'd promote.

#4 isn't really magic. It's just a way to let the compiler fill in the blanks with information it already knows. The benefits are debatable for simple, obvious types but for the hairier generic types you often encounter in C++ it's a godsend.

Of course, the fact that this is so useful might make you wonder if C++'s type system is too complex in the first place.

It's absolutely not "magic", it's clearly-defined, easily-understood syntactic sugar that makes code smaller, simpler, and cleaner.

There is never a case where you have to wonder what the type of an "auto" variable is, it is always the return type of whatever function or method you are invoking. If you don't already know what that return type is, you won't be able to use the result anyway.

std::initializer_list is pretty magical.
I don't really buy that. It enables a syntax that otherwise wouldn't be possible, but so does struct. The only thing really "magical" about it is the optimizations it makes possible, but if that were your concern, it would be the first time I heard anyone complain that compiler optimization is "magical" in any negative sense.
I can answer 2 and 3

2. Apache maintains a list of which compilers support what. http://wiki.apache.org/stdcxx/C%2B%2B0xCompilerSupport

3. The auto keyword isn't supposed to be magic. Rather it's for catching complex types that aren't easily to discover, such as the returns of template functions and iterators, and making it easier on the programmer by not forcing the typing out of long types. The type is resolved at runtime (as best as I am able to tell) and can help clean up some of the messiness of template programming.

No, the type implied by an auto declaration is resolved at compile time.
Thanks for answering those two.

The reason I'm not happy with "auto" is that as a programmer you'll end up hunting down types in source. Even more so if you inherit code from someone else. So we'll add them in comment as mental note instead of properly declaring them?

You call it messiness (visual clutter in the article) but in my experience it'll promote laziness and pitfalls for beginners. It's just a matter of time before you'll see questions like 'why does the compiler infer the wrong type here?' on StackOverflow.

Re-reading my post I see it's easily interpreted as arrogant. That wasn't my intention.

For 'auto'/magic:

There's a looooot of material about pro and contra arguments, if you look at C#'s type inference.

Replace

  auto x = ...
with

  var x = ...
and you can read a good amount of arguments about the benefits and (potential) downsides, and where people deem it useful and clear or where brittle and questionable. The argument you're making was discussed at length when this feature was first introduced. I think it applies 100% here as well.
Of course, if you are a C++ programmer, you should migrate to C++11 as soon as possible.

But do not forget that the improvements given by C++11 do not void all the reasons to not use C++ at all. Avoid C++ if you can.

As has been said a million times, C++ covers applications that are not really suited for any other language. This applies to C as well.

As much as newer languages come about, in the end, you are working with a Von Neumann machine, of which both C and C++ are well suited for.

The only problem with C++ as far as I can tell is that you need to know a lot, not to make mistakes. There are too many ways to do things, that if you don't know what you are doing, you are probably going to do things wrong. However, once you _do_ know, and use libraries like Boost, I think it is difficult to come up with a reason why not to use C++ for lower level programming, with performance requirements.

The problem is that the prerequisite does not apply only to you, but also to all your team. It is ok to use C++ for lower level programming with performance requirements if all the development team knows very very well C++. Even if you fill these conditions during initial development of a project, during the maintenance years, you always happen to have a not so well educated developer. C++ use is a very narrow market.
Code practices and code reviews help with getting beginners up to speed and not clutter the code base. If you remove all experienced developers with inexperienced ones? Surely this will cause problems in any language.

Also, I'll have to disagree with C++ being a narrow market. Just the market where C/C++ is almost required (high performance or low level) is large enough as it is.

Then there is the discussion of which language is _more_ suited for a given task when you are doing higher level stuff that doesn't have high performance requirements. It might be wasted resources to put people with high knowledge of C/C++ to that kind of tasks. As for the language itself, in terms of productivity; _if_ the developers are experienced, I don't see any problem with it. With help from Boost and/or Qt, it is as easy as writing python (almost, sometimes :) ).

There are many reasons why I use C++ only if I must, even though I know it very well.

- Maintaining two slightly different versions of most declarations is unproductive.

- Not having a stack trace when the program crashes slows down debugging tremendously.

- C++ compilers are horribly slow

- Shared pointers are very slow memory hogs but not using them makes memory management a lot more error prone.

- C++ isn't faster than Java any longer, sometimes even a lot slower, unless memory is the bottlenck (which is often the case though)

I use C++ only if I absolutely must determine the exact memory layout of data structures.

What I would like to see is a (convincing) list of why use C++ (in new projects) at all.

In my opinion (and experience) when you need the performance advantages of C++, you are usually within the domain where C is good enough (and perhaps a better choice for its simplicity). When you need the features of C++, you are probably better off with something like Python (not specifically, but in the same "league").

Seeing how easy it is to use a higher-level language combined with C for critical sections, I just don't see the point of C++ anymore.

Disclaimer: I don't really like C++. The only pleasant experience I had with it involved ignoring the STL completely and using Qt (http://qt.nokia.com/). I like C though.

let's say you write a search engine, a route planning system, a database, rule-based NLP (for most ML-based approaches fast, native math libs + python may be great enough because nearly all the time is spent in the math part) on HUGE datasets, etc, etc

pretty much any system involving long list- or set-like types with a decent level of complexity. Most other languages enforce far too much indirection, padding et. al for collection types. Especially generics fail miserably compared to templates for that particular matter. C, on the other hand, will make everything MUCH harder. Especially proper use of RAII and (const) references allow (almost) zero overhead and almost no error-prone pointers (especially zero pointer arithmetic) in the whole system.

I wasn't saying that C++ had no use. I'm saying that its domain is narrower that what's commonly believed.

It is false that C "will make everything MUCH harder". How hard something is to implement in a particular language depends on the problem and the people doing the implementation. C is only perceived to be much harder because people have become overly-dependent on language features (aka "syntactic sugar") and cannot reason about problems in terms that do not require those features.

I'm not talking about using assembly here. It is not a matter of an unstructured language vs. a structured one. I'm talking about features. This is particularly relevant because in many places where C++ is used, the coding standards prohibit the use of more than a limited subset of the language, effectively transforming it into "C with classes".

I don't think that C "will make everything MUCH harder," but with C you'll end up spending a lot of time just getting the groundwork in place before you even start to work on the problem at hand.
C is good and simple but C is not expressive. There are a whole hosts of situation where code has to be duplicated or slightly modified. For instance, it's really hard to do good generic data structures in C without ending up with casts everywhere. Polymorphism is even worse.

For me, that really is the edge that C++ holds over C.

I agree. I kind of wish there was a middle ground between C and C++. C++ is bloated but C is not enough.
Does D not aim to fill this niche? (I suppose in terms of exposure and infrastructure, D is lacking relative to C and C++).
No, it's closer to a garbage collected Algol but with way more features.
People generally master and commonly use only a subset of C++, i.e. C+.
Like the old saying, "you can write cobol in any language".

Polymorphism and "good generic data structures" (in the sense you are implying) are not a necessary requirement of elegant and maintainable code. It is part of the problem that programmers have taken OO concepts as the end-all of good code, and must apply those concepts everywhere even if that means implementing them from scratch at the cost of (unnecessary) complexity.

Large systems have been written in C. Many large open-source projects use C. There is no evidence that these are less maintainable (in general) because of language choices.

Some of these graft OO concepts onto C. GTK is noticeable for this (although it doesn't seem to be too bad for application developers, I'm afraid for those tasked to maintain the libraries themselves).

Procedural programming is not a sin (if "procedural programming" exists at all today, as most of the simplest object concepts have become common practice and are now though as an integral part of it).

Like the old saying, "you can write cobol in any language".

As far as I know, there is no such 'old saying'.

However, The determined Real Programmer can write FORTRAN programs in any language.

Parametric polymorphism (i.e. generics) is not an object-oriented concept.
The problem never was the lack of OO, the problem is that you have to repeat yourself. There will come a type when you have a type that behaves a certain way (certain members, argument of certain functions) and then you will make a type that is mostly the same thing, but then slightly different (maybe one attribute is replaced by something else). You'll have to adapt everything you reproduce a lot of your logic or jump trough very annoying hoops to have your existing logic work with this new type.

If from OO, I could have only Java-like interfaces, it would probably be enough. Implicit type conversions could also work I suppose.

> There is no evidence that these are less maintainable (in general) because of language choices.

I have an example. The Squid proxy code used calling via function pointers everywhere as DIY polymorphism. That made it quite difficult for me (ymmv) to follow the code.

Things like ctags would have worked if they'd used "real" C++ polymorphism.

IMHO. YMMV.

Linux kernel has lists, etc. that can be used as generic data structures. IMO they are good enough for most purposes.
Well the trouble is really polymorphism, and I was actually thinking more about polymorphic data structure: i.e. data structures where the elements are required to have certain methods callable on them. I agree this is typical OO design and could be approached in other ways, but none I know of are satisfactory.
I've had good luck with python and cython when I need to get close to the metal. I'd really like to see a comparison between C++ and that kind of arrangement, some time.
> What I would like to see is a (convincing) list of why use C++ (in new projects) at all.

C is my obvious choice, but...

When it comes to deciding between C and C++, C++ beats C in one aspect: templates. For example, quick sort in C++ performs a lot better than C because templates enable lots of compiler optimizations. (Rest of the C++ features are just garbage for my purposes.)

I just hope next C revision adds some form of template support into the language.

Unfortunately as the number of new projects involving C++ keeps going down, the fields in which C++ jobs are available are getting narrower every year.

Almost all middleware is now written in Java. C# took over the frontend development on Windows. New openings in C++ seem limited to quant fields (bank backends on linux) and driver development.

And Games. AAA game dev (for PC and Console) is almost entirely C++, with some embedded scripting languages (normally Lua, for performance reasons).
> Almost all middleware is now written in Java.

That is a bit worrying with Oracle's recent shenanigans with Java copyright.

I wonder what people like Rich Hicky and Martin Odersky have to say about this subject.

As a long time C++ / C programmer I love every feature here... except one. I really abhor the new auto keyword. Perhaps it's personal taste (I also dislike the "Var" in JS). It really seems to make the code harder to follow with only minimal advantages (that I can see / use/ etc).
While I understand the reason for auto, and see the benefit in less typing, etc, I still do it the old-fashioned waytoo. I prefer be explicit.
One of the reasons I like C++ is that it lets you throw away type safety and still maintain it through abstraction. This sounds awful, so let me explain.

In one project, I implemented an EDSL for performing a destructuring bind on a string (CFG production, actually). The types of the components of the pattern determined what the pattern would actually match.

This was all done in a previous version of C++, so I didn't have variadic templates available. I also didn't want to heap allocate the internals of patterns.

What I did was to store an array of void pointers and a function pointer as private fields within a pattern class. When constructing the pattern, pointers to the things to which parts of the string to be bound were put into the array, thus throwing away their types. BUT, the function pointer pointed to a static method in of a class template, which only operated on the array of void pointers in a type-safe way, precisely because it was compiled with the knowledge of the types.

I use this type of subversion when appropriate, and it's often a very convenient solution to an otherwise tricky problem. Such a thing would either not be possible--or be incredibly inconvenient--in C. It's often very useful to treat different stuff uniformly, knowing that your abstractions can maintain type safety.