The Dark Side of C++ (2007) [pdf]
fefe.de
fefe.de
E.g. the example with file open + close in the presentation is laughable. Every C++ programmer knows that this is something that should be done with RAII. I.e. instead of manual close calls you let the destructor handle it. This is both exception-safe and spares you remembering to add a close call on every possible exit-path.
Also one should point out that C++11 has unique_ptr and shared_ptr which in many cases remove the need for the programmer to manage things by himself.
Unless closing the handle causes an exception to be thrown. Either you never see the exception or your program aborts, and neither one is particularly good if you want to write reliable code.
That is a straw-man argument. If the underlying file-closing API can throw exceptions, they must be caught from the destructor. If that means that they get ignored, then that is what it will have to be (much the same as most C programs ignore the return call from `printf`). Also in this case, the RAII wrapper should provide a member function which can execute the underlying close call early and expose the failure, for users who may be interested in guaranteed reliability.
In any case, provide RAII _safety_ does not intrinsically reduce reliability. If your destructor is executing code which _must_ succeed or be handled at a higher level, then a good developer will not put it in the destructor. No language feature can solve the question of "where should the program stop caring about failure?"
Indeed; this is a useful technique. However, it means that you now have a close() method which you have to call on every exit path, because if you miss a path, that's a path which could have an exception thrown from a destructor. And that basically means you're not doing RAII anymore.
So yes, RAII is intrinsically incompatible with this kind of reliability.
Not true at all. `close` and the destructor should be idempotent. In the main path, `close` will get called and failure will propogate upward. In any other failure path, the destructor will attempt to perform the underlying close and allow the stack to unwind without any further interruption.
Of course, anyone can come up with pathological cases where this is not acceptable behavior from a high-reliability sub-component. And in such a situation, RAII may not be the best answer (nor would lexical scoping i.e. constructor/destructor, for that matter!) But in my experience, this approach is just fine for most application-level code.
http://www.gigamonkeys.com/book/beyond-exception-handling-co...
... and the remaining people realise that use of exceptions in C++,
1. almost always creates a trade-off in performance for strong-exception safety guarantees
2. requires special and strong control of side effects throughout the code base, even when there is minimal benefit
3. increases compile times and resource pressure
4. encourages less knowledgeable developers to inappropriately throw exceptions or make poor attempts to recover from them
5. contain some of the least portable platform semantics and handling.
C++ exceptions contain far greater costs and consequences than many programmers realise. For anything other than testing frameworks, it is debatable that they are worth any benefit at all compared to the alternatives.
There is C++ code out there which reads beautifully and is correct, you just have to work a little harder than in other languages. When you need the performance and control then it is worth the additional effort.
It's not at all unusual, although it is very unfortunate, to run into JavaScript or Ruby code where monkey patching will change the behavior of large sections of code several different times throughout the runtime of an app. This is especially true when the standard library is affected. Debugging situations like this can become very tedious, very quickly.
The point about operator overloading is accepted, but this is not too different from what happens with metaprogramming in Ruby or say macros in lisp.
Even python has some quirks. See: http://stackoverflow.com/questions/1132941/least-astonishmen...
Then why must variables have static types?
Naming conventions (in c++) exist for the programmer to aid the programmer in recovering the semantics of a given expression (which the compiler already understands).
All that being said, I still love C++. I'm glad I know it as well as I do so that I can (usually) avoid problems, but even then I run into compiler (or build!) dependent problems that shouldn't be happening. C++ has problems, and we need to address them. I'm happy to say that even though I am stuck with old compilers that have inscrutable template error messages, time moves on and I am aware of this problem being fixed in newer versions of compilers.
https://news.ycombinator.com/item?id=4969372
http://news.ycombinator.com/item?id=4539251
http://news.ycombinator.com/item?id=3712292
______________
this mechanization of the lang spec in Coq looks interestng
Minimizing the use of OOP helps avoid the language's sharp corners. With C++11, I highly recommend abandoning the "C with classes" style.
Out of intellectual curiosity, what resources (books, sites, etc.) would be recommended for modern, best practices C++?
Blergh. This stuff is why I use Python (with snippets of C for speed): when I do something stupid, I get an error message and line numbers, not a faceless segfault (+even when I get a C segfault, I can still get the python stack back with faulthandler..)
Languages do not pass the usual development cycle that includes collection of requirements, beta-testing and bug fixing. C++ have some obviously stupid design decisions that apparently will never be fixed.
Strangely or not, people tend to approach languages religiously rather than rationally.
Languages are like holy scripts that are written by one or a few people that are perceived like gods, and there is no proper critism or improvement following the development of a language.
Hence what we have today.
One of the most popular languages is full of stupid design mistakes that will never be fixed, they rather die with the language.
Actually, an example of a language that fixes many of the C++ problems is C#. But it inherently cannot be a replacement of C++.
Again, people are not rationally thinking creatures.
And to all who are not rationally thinking, I just say: fuck you.
D may be superior to C++, but if you have to build a firmware in one year and you will need 20 developers you cannot use this language since you cannot hire that many experienced developers and the D compiler may not even target your platform.
Even luck and being in the right spot at the right time by coincidence play a large part. Consider Javascript, which was never designed to do all the stuff people use it for nowadays. But for all its flaws it solved people's problems at the right time and therefore got popular. It was the same with C and C++.