Is C++14 a better language than C++98? It's hard to tell (I think it is - I think C++ is worse than C, but having gotten to C++98, perhaps it helps more than hurts to add all that other shit), but it's not an interesting question anyway because the upgrade is easy enough and it's worth it for most people for their specific reasons, so C++98 will die out.
But then it's not like Google aren't upgrading to the latest C++ standard, they're just doing it slowly AFAIK.
I don't see what the big deal is. C++ is probably the most gigantic and complex language I am likely to ever use... but you don't have to use the vast majority of it if you don't want to. If you want to stick with C-style coding, you pretty much can, if you don't want OO or STL or ++11/14 features -- nothing is forcing you to write those features into your code. But when you want access to them, there they are; and if suddenly you find yourself needing a particular library that only exists in C++ (as so many graphics and physics engines do), you can get access to that as well.
As soon as you need multithreading, or sorting of hash maps, or even basic string operations, knowing you can reach for them in pinch rather than find the C alternatives or build your own, seems like a big bonus to me (assuming a comparison to C).
I work with a few who write their C++ like it is C (pointers thrown around, no const-correctness, memcpy instead of copy constructors etc. etc.) and it is horrible to read. There is no indication of lifetimes of objects, nor any indication of ownership. No RAII, no exceptions, nothing. It is dangerous.
You are rewarded for writing C++ safely because you won't have to fix any bugs and you can offload all the work onto the compiler for checking types and safety for you.
Like you, though, I don't understand people who get red in the face about C++ and go into a profane rage. It is just a language after all.
Um... why? If the development support does not include a garbage collector, I have to be very careful about these things. And, I am. Very careful indeed. I just use the approach I do in C, and assume NOTHING from C++. Honestly, I do NOT assume that the language system, compiler or run-time can do it properly. I have been bitten too many times.
I do presume a garbage collector at the very next level up.
Yes, you may find my code "horrible to read". And, yes, I have gone into profane rages over C++ code. It happens when the code bullies me -- with hopeless error messages for simple typos. When simple changes cause the application to no longer link. When simple changes cause massive explosions in object size. In fact C++ is so complex, it encourages cargo cult programming. Not just use of libraries, but enforced cargo-cult when USING the libraries. Because, raisons.
Not just a language -- hell-spawn. Sorry, "modern hell-spawn".
Ownership is very important because if you don't know who owns it, who will clean it up??
If you don't know how long an object will be around because you've got a pointer, it is now a dangling pointer and attempts to use it will cause chaos. So object lifetime is important too.
The error messages are usually quite helpful. clang's messages are more helpful for gcc, I have found.
C++ is complex, but you can still write safe code without using any of the complexities.
Which works, except when it doesn't. Which results in stuff like reference counting in the codebase. Which, of course, changes on a whim.
Example: the CEF3 library (chromium embedded framework).
Reference counted objects. Which requires source code changes depending on the version of CEF 3 being used. Requires VERY deep analysis to determine what to change in the using code. Really -- because the objects participate in a multi-threaded library.
So, most code ends up as "cargo cult".
Since my code doesn't fit into the CEF3 object model, I do the contortions needed -- building another layer.
Reference counting is code smell that you don't have a clear ownership model.
Take a look a Rust for something more along the lines of what I'm talking about. There's been quite a few people who've re-written their C/C++ code to Rust only to find out that they didn't have a clear ownership model and found architectural improvements because of it.
If your acquisition of a resource fails or initialisation fails, throw an exception in the constructor.
C++11's threading support library in the STL should help your threaded problems.
If you need containers of items, put them into an STL container. Don't allocate them with new - write a move constructor for your item and it'll be moved. Or a copy constructor; follow the "rule of 5" if you have pointer-held items in your object (probably best not to), or "rule of 0" and let the compiler do it for you. std::move your items into the container.
Use const references if you want to let something else use it, ordinary references if you want them to modify it. Or if you must use naked pointers, put them in a unique_ptr so it gets cleaned up eventually (http://en.cppreference.com/w/cpp/memory/unique_ptr). Or shared_ptr in other areas (see Stroutrup 5.2.1 in C++ 4th edition).
If you need naked pointers, allocate them on the heap but wrap them in std::unique_ptr or have a vector of unique_ptr. If your objects are child items in a class hierarchy (e.g.. ChildClass : public BassClass) or the base class is an abstract class and you want to have a generic STL container (like std::vector<BaseClass* >) to store all base and child items in one neat place, you will have to use pointers (as you can't have std::vector<MyAbstractBaseClass> but you can have std::vector<MyAbstractBaseClass* >), you will need to take care in the containing object's destructor to clean up this container, eg. while(!vector.empty()) { delete vector.back(); vector.pop_back(); }
You shouldn't need reference counting. A read of Stroustrup's C++ Fourth Edition book and the "tour of C++" section toward the beginning will help you immensely.
From what I know, having the chance to ever find a job on my area where one can use proper C++ is very thin.
But that's not the case. No shipping version of C++ is memory safe. In fact, this is exactly what the article is about.
You want to keep raw pointers, etc. confined to private class members, initialize memory only within the constructor (if possible), and free memory at the destructor. The user/public API should not expose unsafe stuff. With all this, RAII will give you a nice expectation of lifetime, etc. Plus you're able to use something like tcmalloc.
I often find a difficult issue arises when you have a large data structure that you want to free before it goes out of scope (to reclaim some memory). In this case, adding a "clear" method that frees the internals is handy. The destructor will call clear() but you can call it at any time. No harm done if it's called twice.
The next thing is const-correctness: if you follow it then any C-like code underneath should be relatively safe.
Not using copy constructors is just awful. Memcpy has a time and a place: at the low level (eg; I use it for serializing to a buffer). If you're using memcpy for classes you're probably doing something wrong.
Exceptions are a place where you see a wide gamut of safety. Some people don't use them at all: which isn't great. Others add hundreds of lines of code by wrapping everything in a try/catch. Not sure where I stand here, honestly. There's a point where you're catching exceptions that just aren't going to happen...
Anyway, it's difficult to have a reasonable discussion over a topic where said topic has religious dimensions for one of the involved parties.
C++ biggest problem are all the design decisions to fit into C's tooling and its compatibility.
That said as someone who hasnt done a lot of C or C++, i'd like to think learning the new way is best, otherwise it's hard to know where to start.
In the 80's Assembly was the only way to go, if you were targeting consoles and home systems.
Higher level languages were the managed languages of the day.
When the SDK started to push for C, like on first PS, they were forced to move. Still the code was pretty much inline Assembly wrapped in C, until they were confident to write more and more in C.
Similarly when around PS 3 time, the SDKs were moving into C++, the majority took advantage of the C compatibility and used only as much C++ as required by the SDKs.
Only recently some started to do the transition to embrace C++.
Likewise if in the future language X becomes the only way to target games for platform Y, and they a market that they need to be in, they will eventually adopt it. Of course writting big chunks in C++ until they can be convinced it is ok to just use X.
The features are dependent on each other though. The flipside of my example elsewhere in the thread: if you want to use templates to eliminate repeated code, you more-or-less need to make any classes you want to template over use RAII (or else do very error-prone partial template specialization to ensure your things are initialized and deininitialized correctly). So then you have to use exceptions, because if you're doing complex logic in your constructors then you need a way to report failure. So then you have to make your code exception-safe, which means making everything else RAII.
Lambdas would mean I could bin all those structs with bool operator()() for find_if that I have to litter my code with.
"Boost.Atomic is a library that provides atomic data types and operations on these data types, as well as memory ordering constraints required for coordinating multiple threads through atomic variables. It implements the interface as defined by the C++11 standard, but makes this feature available for platforms lacking system/compiler support for this particular C++11 feature."