You're absolutely right. Using some C++ features, when appripriate, really helps. Of course you can do it all in C, but some things are really painful to do in C (for example handing dynamic reallocation when you have to use things like vector of string and the likes).ilari wrote:I think C++ is a very good tool when it's used by people who know what they're doing. It has served as quite well for Cute Chess where we need a good combination of low-level control and high level features. The bottlenecks were easy to identify and thanks to C++ they were also easy to optimize.wgarvin wrote:I completely disagree with this.ilari wrote:C++ should not be thought of as better C - it's a different language and it should be used differently. Fruit is a good example of how to use C++ without really using C++, and Stockfish is a great example of how C++ should be used.C++ is a horrible language. If you have to write a high-level program and you can't just use something like Python, then I guess C++ can get the job done. But for low-level code, most of its language features are a double-edged sword, making it easy to bleed away the performance advantage of C without even noticing.
You don't have to use every feature of C++, that's not what I was trying to say. For example we don't use exceptions at all. But we do use a lot of RAII, polymorphism, generic containers, Qt's unicode strings, etc. And in the very few places where we needed to minimize CPU or memory consumption, we did it with very C-like code. Rejecting C++'s high level features completely wouldn't have made our program more efficient in any noticeable way.If you want to write "nice C++" then go ahead, but writing "proper C++ code" with lots of RAII, virtual functions, default constructors that initialize everything to zero or NULL, etc. is a good way to get slow programs. Plus nobody, and I mean nobody, can reliably write exception-safe C++ code that does anything tricky. Exception-safety in C++ is ridiculous and difficult. If you care about having correct programs, a much safer way to write them is to turn exceptions off and write all of your code without them!
So you do advocate using C++'s features and even STL where they make sense. That was exactly my argument. There's no good reason why Fruit couldn't use std::string instead of char* for example. And I doubt you could make Stockfish much faster by converting the code to the kind of "better C" used in Fruit. BTW, you can declare variables in the middle of a function in C, unless you're using some ancient C89 compiler.Anyway, for a programmer familiar with C it is very easy to use C++ as just a "slightly more convenient C". You can put little inline accessor methods in your structs, you can declare your variables in the middle of a function, and you can use a little bit of RAII style for some convenient things (such as profiling, or making sure a block of memory gets freed when exiting from a function that has a complex control flow). Sometimes it might make sense to use C++ templates a little bit, to reduce source code duplication (you'll still have near-duplicated code in the binary, but sometimes that is what you want, and templates might be less ugly than macros for your specific use-case.. it varies). For some kinds of code, std::vector is a much simpler way to get obviously-correct code than some manual malloc/free would be. Another pure win is std::sort, you can use it on ordinary arrays or std::vector or whatever else, and it will usually be faster than qsort() or anything else.
I don't really like this "be wary of this and that" mentality of premature low level optimization. I think it's better to just first write the code without worrying too much about low level performance and then profile the code. After profiling the bottlenecks can be optimized.A big benefit of using C++ as a "better C" is that performance-wise, it doesn't cost any more than the equivalent C code. Be wary of constructors that initialize everything in a performance-critical struct (e.g. something you'll allocate a vector of thousands of, should have a do-nothing ctor or just a default ctor). Don't use STL (other than for convenience in non-performance-critical code), don't ever use the iostreams garbage, turn of RTTI and don't ever use dynamic_cast, and DISABLE EXCEPTIONS at least for your 32-bit builds. (In 64-bit builds the performance cost of having them enabled is pretty much zero, just a tiny bit of lookup-table bloat). Don't even use virtual methods unless you would have used some sort of dispatch anyways in your C code (but generally you should try not to use them in any performance-sensitive code). C++ is just as fast as C if you don't use any of the language features that have some extra cost. If you stick to "C subset" plus some conveniences like inline methods, then you can't really go wrong!
It's clear that we are developing completely different kinds of programs. I don't view modern hardcore computer games as typical desktop applications. But I know how crazy it is at companies like Naughty Dog where they're trying to squeeze every drop of performance out of very complex hardware using Assembly or whatever. I recently read an article about the development of Starcraft. The stuff about linked lists sounds exactly like the kind of hell that I will be avoiding like the plague.This really varies with application domain. Its mostly true in computer chess, but (for example) mostly false in games. Modern games spend about 90% of their time spread across 50% of the code (millions of lines of it).ilari wrote:And not all code has to be fast. In a typical desktop application only a very small percentage of the code is performance-critical.
But to actually see any benefit from using C++, you need:
1/ to understyand deeply the language, and it's immensely complicated. I don't think there is another language that is even close in terms of complexity. Just reading Bjarn Stroustrup's book on C++ (although very well written) is a reminder of that fact. So there is a pretty steep learning curve. The C++ FQA link that I posted previously is also a very good reference of all the traps that C++ tries to set for beginners (and even for people who don't think of themselves as beginners, but actually are, because C++ is more complex than they imagine).
2/ you need to know what to use, and what not to use, and when. In other words, have coding guidelines, that are based on knowledge and experience. You can gain that knowledge and experience yourself, by years of suffering and rewriting your code bcause it was badly designed etc. Or you can trust others: the Google coding guideline is very good IMO. It has already helped me to refactor my code a little, and make it more flexible, easy to extend and reuse.
So, C++ is now useful for me, although not without pain. Hopefully this pain is teaching me how to use it better, and there will be less and less pain as I understand how to make efficient C++ design. And it does help you do things that would be a nightmare to handle in C.
But it is horribly complicated, and full of tricks and traps. This is mostly because of historical reasons: started as C with classes, things were added, and retrocompatibility had to be preserved, and after years of evolution it became so complex no human can *fully* understand it (perhaps Bjarn himself?).
What I'm really hoping for is a new language that adresses these issues, and keeps the high level potential of C++, while keeping the low level potential of C. And this language exists, it's called D. The only problem is that it's really so new and scarcely used. And it's hard to know if it will be popular in years to come: is it worth switching to D now ? Or learning C++, which is a really hard for someone like me who really "thinks like a C compiler" ? We'll see
PS: One of the languages that I really liked, which is also my first compiled language, is Pascal (before I'd only written in Basic and Assembly). As a high level language, it is a lot easier and a lot better IMO than C++. But when it comes to the low level, nothing comes even close to C (in terms of speed & memory, but also in terms of having the control of what exactly happens and being able to hack things manually byte by byte when you want/need to). And the fact that C++ kept it's C subset (although slightly modified, still useable) makes C++ simply unavoidable (however ugly and complex it may be).
Lucas (a partially repented C++ hater)
