3 ms·
I would say that the lack of a standard garbage collector ("smart" pointers do not count since programmers must manually break cycles and decide among smart poi
by betterunix 13y ago
I would say that the lack of a standard garbage collector ("smart" pointers do not count since programmers must manually break cycles and decide among smart pointer types) is a pretty serious deficiency. I would also point to the abysmal error-handling support in C++; you do not even get a reliable way to report errors that occur in destructors.
Really though, my big issue with C++ is that the high-level features are bogged down by low-level details -- if I wanted to deal with low-level details I would not be using high-level features in the first place. Why should I have to manually determine how to capture variables in a lexical closure? Why should I have to manually declare "virtual" inheritance to deal with the multiple inheritance diamond? Why are destructors not virtual by default? Why are string literals still pointers to character arrays, why are arrays still not bounds-checked, why are integers still fixed-width (and why are integer overflows not reported as errors?)? Yes, these things all make sense sometimes but in most cases they are the opposite of what you want -- you should have to write more code to get this behavior than to avoid it.
- SamReidHughes 13y agoWell, I agree with your complaints about the annoyance of lacking garbage collection, but not everything you complain about. The only nit I really disagree with you on in this post is that it's certainly reasonable that you should have to manually determine how to capture variables in a closure, in C++, because of the nature of the language. Also, many other languages avoid the multiple inheritance diamond simply by not allowing multiple inheritance (and others do it a bit better). The other questions, you know the answer to, and the answer is very obviously performance or compatibility with C (or just bugs in the language). But I'm not claiming that C++ is less annoying to use. I'm saying it has better facilities for making high-level abstractions. That's because of its type system, and you have to go to something like Scala, Haskell, or other statically typed languages, or maybe something homoiconic like Lisp, or something odd like Oz, to really beat. You can make better, more accurate abstractions in C++ than in other mainstream languages, and they're safe and solid, while in languages like C# you often end up having to resort to unsafe conversions.
- betterunix 13y ago"The only nit I really disagree with you on in this post is that it's certainly reasonable that you should have to manually determine how to capture variables in a closure, in C++, because of the nature of the language" I disagree here. First, the nature of the language is no excuse -- I am criticizing the nature of the language to begin with. Second, in this case, there is a sensible default: always capture by value. If you need or want to capture by reference, create a reference and capture that -- which is already what people have to do when they return a closure and use smart pointers to maintain the lexical environment. "The other questions, you know the answer to, and the answer is very obviously performance or compatibility with C (or just bugs in the language)." Except C++ does not maintain compatibility with C, and "performance" is not an excuse either. If performance is a concern, create a keyword to disable default behavior; e.g. if you want to not have a particular destructor be virtual, then there should be a keyword for that. Even compatibility with C is not an excuse -- already the extern "C" syntax is used to disable the name mangler, so why not go all the way and have it also disable things like array bounds checking and creating string objects for string literals? Basically, C++ is a language that makes unsafe code easier to write than safe code; this is the opposite of what a high-level language should do.
- mihai_ionic 13y agoBecause in C++ the rule is "you only pay for what you use." All the things you want would incur a performance penalty were they the default.
- betterunix 13y agoThat is a typical trade-off for high-level features: you incur a (constant factor) performance penalty to gain programmer productivity. If you need to avoid performance hits wherever possible, the language should give you an escape hatch; default behavior should make developing reliable software easier, not harder.