View Full Version : Why C++ …
I just came across this quite insightful article while browsing through old bookmarks:
http://gamearchitect.net/Articles/WhyC++.html
OneSadCookie
2006.10.27, 08:30 AM
Most of it is fairly uncontroversial, but I don't buy his argument that C++ is better than C for the core engine functionality. Yes, you end up writing virtual function tables in C, yes you end up re-implementing generic data structures, and yes, you need a good grasp of how to use the C preprocessor. I don't think that those outweigh the downsides of using C++, though.
He's already said that if you value productivity, you use a productive language, which C++ is not. Why, then, turn around and say that you should use C++ at this low level because it's marginally more productive than C?
He also says that the STL is almost always faster than code the average programmer will write by hand. This may be true, but isn't really the point -- if the STL is your bottleneck, you still need a talented programmer to write the special-case code to solve the performance problem. What's more, they've got to fight with trying to understand *why* the STL is the performance problem before they can begin... at least C code is easy to analyze!
And if you're having problems with programmers who don't know about asymptotic complexity, or cache coherency, or whatever, in a professional environment, it's time to hire some new programmers. Those ones'll probably be fine programming Java or .NET for some big corporate, and probably earning more than you and putting in fewer work hours -- don't feel bad about letting them go :p . You want the programmers who know how to program at all levels, from the machine up to the mathematics. Fortunately, many of them want to program games ;)
icklefrelp
2006.10.27, 11:32 AM
Back in the murky depths of time, when I started in the games industry (mid 1996) it was very different. I was a die hard 68000 assembly programmer although C was my high level language of choice, Almost everyone coded in straight C, apart from the times when we needed to go really low level, when we'd do MIPS assembly (PS1). C++ was ok for tools, but noone used it for game code.
Since then I always considered myself a die hard C coder, I hated C++ (probably for no real reason other than I considered myself a die hard C coder.) Over the years I have been dragged kicking and screaming into the C++ camp, in that I will rarely write straight C code anymore even in my own projects at home.
However in many ways I long to go back to writing in C and ditching the things I dislike about C++, but use them because they are convienient, rather than efficient (operator overloading being something that comes to mind). But I have such an investment in C++ now (in terms of a body of code), that it's an awful lot of work moving away from C++. On many occasions I have started a project saying C only or perhaps Objective-C where I can use C for the bits that really do need to be fast, but so far I have always gone back to my C++ codebase.
I can't see the situation changing, too many people like the things that C++ gives them, that makes their jobs easier. Even though I may be more productive now using C++, I know that I'm not as happy programming as I used to be when it was straight C and Assembly language.
akb825
2006.10.27, 02:50 PM
I do enjoy using C, and for the core of my current project, I'm doing everything in straight C, since it will have better portability. However, when I use the framework I'm making now, I'll be using C++. I just don't want to have to go through all the trouble of getting all the inheritance etc. to work in straight C.
For me, I think C++ is pretty much what I want in a language for complex projects. It's still somewhat low level, but provides simple and powerful tools for things like polymorphism and templates. I don't need, or even want, über high level language constructs. (hell, I've never even heard of closing) I like coding in C, but I want better object oriented tools for polymorphism, and C++ provides that. Things like templates turn out to be very useful because of the convenience and you end up getting the efficiency as if you created the class for each object. (though at the cost of code size) Other things like operator overloading are gravy, IMO. They aren't really necessary, but can be very convenient, both for math and data structures. I think it's pretty cool that you can use any data structure like an array, assuming you have a way to look up an index. Or with an iterator, you could do something like
object = *itter++;
or
element = itter++->getWhatever();
Also, for things like data structures, it makes it very easy to have a compare that everybody can agree with. (ex: would you use compare, compareTo, compare_to etc.? Instead, you can just have operator >, operator <, and operator ==, or any 2 of those) It also makes it so you can use primitive types just as easily as objects.
AnotherJake
2006.10.27, 04:00 PM
On many occasions I have started a project saying C only or perhaps Objective-C where I can use C for the bits that really do need to be fast, but so far I have always gone back to my C++ codebase.
That's funny, once in a while I will start a project and say that `I am using C++ only this time', and I wind up going back to my C codebase. I think it has to do with the fact that my mind tends to think in terms of how I can solve problems using C most of the time. I have programmed so little C++ in the last few years that good techniques are all but forgotten.
That is a good little article, and I liked reading it until it seemed a little rambling near the end. It seems to me that there are good and bad coding styles in both C and C++. I have seen lots and lots of really poorly done C++, and that has helped turn me away from it. OTOH, I've seen some damn clean C++ that made lots of sense and has enticed me back to it as well.
I take issue with two of the points he was saying about C though, because they both have more to do with coding style than any deficiency of the language itself:
First, data structures being packed with function pointers is not accurate. All you will likely ever need is one pointer each for: init, update, render, destroy. And even those are not required. A better way to do it that I have learned is to create a dispatch table in my scene graph manager that simply issues callbacks based upon a simple type variable in the data structure instead of pointers, which saves more space -- the equivalent of three less pointers in each entity. It is a super simple and powerful technique that I prefer over function pointers stuffed in structs.
Second, macros generally suck. I hardly use them at all and have found that where there is a macro there is usually a better way to code the solution in the first place.
However, I entirely agree with the argument that he makes for C++ by essentially pointing out that even if you know for a fact that C is better, the industry disagrees with you and if you get into the big-leagues you will have no choice but to program in C++. That is entirely true. Indeed, even Carmack was forced to switch!
OneSadCookie
2006.10.27, 07:26 PM
I don't need, or even want, über high level language constructs. (hell, I've never even heard of closing)
Closures, not closing.
How do you know you don't want them, if you don't know what they are? Because believe me, you want them ;)
akb825
2006.10.27, 09:31 PM
After looking it up in Wikipedia, it looks like it's used with inner functions, which I have no desire of using. So there. :p
Skorche
2006.10.27, 09:58 PM
After looking it up in Wikipedia, it looks like it's used with inner functions, which I have no desire of using. So there. :p
Not really. They are more like code blocks that have a persistent scope and can be passed around as values. They are often the killer feature of languages that support them. Way, way more useful than inner functions.
OneSadCookie
2006.10.27, 10:01 PM
If you've ever used an anonymous inner class in Java, an anonymous delegate in C#, a block in Ruby, a lambda function in Python, or many other similar features in many other languages, you're using a closure (or perhaps a slightly more restrictive cousin).
And if you've used those languages and haven't used those features, you weren't using the language right... and if you haven't used those languages, you owe yourself an education :p ;)
It's the one thing I miss most moving back to C, C++ or ObjC from just about any other language.
akb825
2006.10.27, 11:58 PM
I've used inner classes with Java, so I think I know what you're talking about. I will admit that I've not had that much experience with different languages: I've used C, C++, ObjectiveC, and Java. (the latter being limited to school, since I very much dislike it; I liken it to C++ without the C) In later classes I will use other languages, however. I would say, though, that my coding style seems to fit very well into the C and C++ paradigm. (where I use the one that makes the most sense for what I'm doing; I limit my ObjectiveC use to things I must use with a Cocoa interface) My preferences may change, but I certainly don't feel "trapped" when using those languages.
Skorche
2006.10.28, 01:31 AM
Ah, anonymous inner functions. How to count the ways I hate thee. The syntax is so utterly gross.
On the other hand, you could take the advice that the software design professor at my school teaches and never ever use them. They of course are the spawn of the devil (along with their evil cousins, the inner classes) because they promote bad OO design. (or some nonsense like that) Clearly, if you were a diligent Java Swing programmer, you would write a million classes with a one line action method. :rolleyes:
Steven
2006.10.28, 05:27 AM
At Berkeley in CS61A we use Scheme. Being a LISP-esque language, we have lambda functions. Before I started using them, I never would have though I would need anonymous functions. But now that I've seen the power of higher-order functions like map and accumulate, I've started to realize just how amazing they are...
Learn Scheme! You'll understand programming so much better... and you'll realize that C++ really sucks :-p
akb825
2006.10.28, 06:42 AM
Can you give me a real-world example of how they would be used/what's really great about them? (just out of curiosity, since I really haven't heard much about lambda calculus)
I think the problem with closures and other concepts in higher-level languages is that they are sort of taught as an addon to OO, and that is really not true. People tend to start with Java, C, C++, and Objective C, maybe some flavour of BASIC, and have in mind only the object metaphor. And this is where bad coding style comes from.
Closures, lambda functions, etc are actually completely separate concepts that are compatible with basic OO. In the toolbox metaphor, if the basic OO concepts are the screwdrivers, hammers, and wrenches, then closures and friends are the power tools :)
Note how the article says that it's not a good idea to stick to pure C++, but rather to use it in combination with some more dynamic and powerful scripting language.
OneSadCookie
2006.10.28, 08:05 AM
I'm not sure anyone was advocating adding closures to C++, rather trying to explain to akb825 why C++ isn't the be all and end all of computer languages :)
akb825
2006.10.28, 02:26 PM
I'm not saying it's the be all and end all, I'm just saying it seems to fit my coding style very well. Right now I'm kind of curious to see what these "power tools" are.
Steven
2006.10.28, 04:40 PM
Well, here's something cool:
(define (square x) (* x x))
(define (tree-map func tree)
(make-tree (func (datum tree)) (map (lambda (x) (tree-map func x)) (children tree))))
If you then call (tree-map square tree) it will return a copy of tree with all the data in the tree squared.
You'll notice that functions are just data, so you can pass them around without any messy function pointers.
The way this tree structure is laid out is with three functions: (make-tree datum children) which takes a datum, and a list of child trees. (datum tree) returns the datum, and (children tree) returns the list of children.
Map is a function that takes a function and a list, and returns a list whose elements are that function applied to each element of the list.
Also, function calls always precede the arguments (even for arithmetic) so (* x x) is like x * x in C.
akb825
2006.10.29, 12:53 AM
That's kind of cool. So it's basically a simpler/quicker way to do function pointers? It does seem to broach on the issue of readability, though.
Skorche
2006.10.29, 01:32 AM
I thought functional code was really hard to read too before I took a programming languages class. Probably one of the best classes I've taken. Now I still think it's fairly hard to read, but definitely allows some very elegant and simple solutions to a lot of problems.
I also liked OCaml better than Scheme as far as functional languages go. Scheme has a very simple straightforward syntax, but is fairly hard to read. OCaml has a much more natural syntax. (Without millions of ()'s) Of course, Scheme's syntax allows code to be manipulated as a tree, OCaml cannot do this as far as I know.
I'm not saying it's the be all and end all, I'm just saying it seems to fit my coding style very well...
Does C/C++ fit your coding style, or does your coding style fit C/C++? ;)
Steven
2006.10.29, 05:07 AM
The readability isn't so bad if you have both proper indentation/linebreaks and proper syntax coloring, neither of which are possible here :)
And yes it's kinda like function pointers, except it's more flexible - no types, no pointers, and you don't have to give everything a name. You could just as easily pass (lambda (x) (* x x)) instead of the square procedure and it would be just as happy.
akb825
2006.10.30, 01:57 PM
Does C/C++ fit your coding style, or does your coding style fit C/C++? ;)
Well, I learned first in Java (for school), but as soon as I taught myself C/C++ shortly after, I have been using it exclusively for my own projects. Since it was pretty much part of my learning process, I'm sure it helped shape my coding style. But I'll put it this way: whenever I'm using C/C++, I never feel "trapped" or that there's something that I need that's missing. I suppose that could partially be because I haven't experienced some of the features of other languages. However, from what I've seen here, I haven't seen anything that I really want to use.
Well, I learned first in Java (for school), but as soon as I taught myself C/C++ shortly after, I have been using it exclusively for my own projects. Since it was pretty much part of my learning process, I'm sure it helped shape my coding style. But I'll put it this way: whenever I'm using C/C++, I never feel "trapped" or that there's something that I need that's missing. I suppose that could partially be because I haven't experienced some of the features of other languages. However, from what I've seen here, I haven't seen anything that I really want to use.
Ruby has spoiled me.
OneSadCookie
2006.10.30, 03:31 PM
Ruby has spoiled me.
Yeah, I think Ruby is the only language I use where I don't constantly go "well, if I had *that* language feature, this would be easy..."
Najdorf
2006.10.30, 07:18 PM
After using cocoa a bit I kind of "got" the idea behind objective-c and am quite impressed (you kind of do everything by overriding existing methods :blink: ). Indeed it allows for quick and clean use of the huge API.
But for a game, hmmm, I dont think you need as much "generality"... a "bare bones" object oriented framework is fine, such as Blitzmax's or the more simple C++ stuff.
Since you are not using "ultra general" code provided by others but your own, likely much more "to the point".
After using cocoa a bit I kind of "got" the idea behind objective-c and am quite impressed (you kind of do everything by overriding existing methods :blink: ). Indeed it allows for quick and clean use of the huge API.
But for a game, hmmm, I dont think you need as much "generality"... a "bare bones" object oriented framework is fine, such as Blitzmax's or the more simple C++ stuff.
Since you are not using "ultra general" code provided by others but your own, likely much more "to the point".
"What's with all the "quotes"?" :p
Anyway, if you have a more powerful language to your disposal, you can write very general code that works very quickly, but still have the choice to speed things up by creating specialized code, or even dropping to C, most of the time.
For projects consisting roughly of more than a few thousand lines of code, probably even smaller ones, the overall complexity of a program written with high level scripting + C/C++ will worst case rival that of a pure C/C++ program with the same task.
The only potential downside of using a scripting language is performance, and that can be helped.
Also, working with a language that is less restrictive allows encourages to explore new ways of doing things, imho.
Andrew
2006.12.06, 05:18 PM
One language I really liked from my programming languages course was Gopher, a simplified version of Haskell (http://en.wikipedia.org/wiki/Haskell_programming_language) which has since been supplanted by HUGS (http://www.haskell.org/hugs/). I liked Haskell's syntax more than LISP's, primarily for its brevity. Here's some further reading (http://www.haskell.org/haskellwiki/Introduction) if you're interested.
SOUCHAN
2007.03.13, 05:48 AM
[...] whenever I'm using C/C++, I never feel "trapped" or that there's something that I need that's missing. I suppose that could partially be because I haven't experienced some of the features of other languages. However, from what I've seen here, I haven't seen anything that I really want to use.
Ed (a.k.a. fax) linked me to an article recently which covers that point very well. You can find it here:
http://weblog.raganwald.com/2006/10/are-we-blub-programmers.html
I'm sure you could talk to any programmer who has used something more high-level than C++ and you'd get the same response. When C++ was all they knew, it felt perfectly natural. Not so now that they've used lisp or python or any other language which ranks more highly on the blub scale.
And like Keith says, if you haven't used any of those languages, you owe yourself an education :-p
C++ still has it's place, of course. It's just not a good tool for every job - indeed, I'd say it's a bad tool for most jobs. Knowing the alternatives will make your life vastly less stressful when you encounter a job which C++ doesn't solve easily.
akb825
2007.03.13, 06:04 AM
I'm in the last week of my programming languages class. We've gone through OCaml, Python, and we just finished Prolog. Of all of those, I think Python was my favorite, excluding some superficial problems. (namely using whitespace to determine scope and implicit variable declaration) However, while trying to keep an open mind, I still prefer to code in C++, due to keeping enough low-level control to try and make sure that I do things as efficiently as possible along with still keeping at least some high-level concepts intact. Sure, there's some corner cases that can sometimes cause some problems and/or ugliness with things such as templates, but there's also plenty of headaches that can be caused due to Python's dynamic types or with any other language. Bottom line is, I think C++ still fits what I do the best.
OneSadCookie
2007.03.13, 06:17 AM
You'll know you've become a good programmer when you change your mind ^_^
unknown
2007.03.13, 11:18 AM
One language I really liked from my programming languages course was Gopher, a simplified version of Haskell (http://en.wikipedia.org/wiki/Haskell_programming_language) which has since been supplanted by HUGS (http://www.haskell.org/hugs/). I liked Haskell's syntax more than LISP's, primarily for its brevity. Here's some further reading (http://www.haskell.org/haskellwiki/Introduction) if you're interested.
Personally I really dislike the haskell syntax for many reasons like indentation as syntax and theres a lot of very arbitrary little things which bug me, it happens in haskell just like it does in mathematical notation (http://video.google.com/videoplay?docid=-2726904509434151616).
Of course, the language has many incredibly useful things that lisps do not (pattern matching, implicit currying, algebraic types, type inference etc)...
Thing is, in (on) lisp you can write code-transforming macros which means (combined with closures and functions as a first class data type) that any language feature you like the look of you can easily implement in lisp itself (including all mentioned above, object systems, domain specific languages, declarative programming and so on..).
But once you've read SICP (http://mitpress.mit.edu/sicp/full-text/book/book.html), and realised that programs you use daily crash due to being programmed in pointerful, non garbage collected languages by humans, everytime you try to do even a little meta-programming in C++ you just end up in template hell: more bother than its worth to try and write correct programs in any C based language.
ThemsAllTook
2007.03.13, 12:12 PM
You'll know you've become a good programmer when you change your mind ^_^
Your definition of "good programmer" differs vastly from mine.
OneSadCookie
2007.03.13, 03:47 PM
I don't believe you can be a good programmer without the ability to know when your tools are hurting your ability to produce a solution. That means that (amongst other things) you must realize that no one programming language is the be all and end all, so you could not make a statement like "I only need language <X>".
I personally believe that C++ is not a good language for *any* task, for reasons I've often explained before, and the people I've met who I consider to be good programmers tend to agree. I've only met one who didn't, and he programmed C++ like the standard library (though somewhat more readably), not like he wished it was Java, as most people do.
akb825
2007.03.13, 06:37 PM
I most definitely don't program like I wish it was Java, as I don't particularly like Java. I simply believe that C++ is my best choice for what I'm doing right now. I may decide to refine that later and choose to use embedded scripting languages etc. to augment what I'm doing, but I haven't needed to do that yet.
OneSadCookie
2007.03.13, 07:26 PM
My philosophy is that at any given time, there are three things that you may care about when programming. From least common to most common:
1) You want to write fast code.
2) You want to write correct code.
3) You want it to be easy to write code.
Unfortunately, these tend to work against each other.
If you want to write fast code, you need a language which takes you close to the hardware. It needs to provide a fairly direct mapping between the "high-level" source and the assembly, so that you can pinpoint problems in the assembly and know exactly what needs to change in the high-level code to fix them. The only language I've ever used which does this is C. With C++, as soon as you get into references, copy constructors, operator overloading, etc. there is too much going on for that direct correlation between source and assembly to exist.
If you want to write correct code, you need a language which prevents you from making as many errors as possible. That implies a strict static type system, array bounds checking, an inability to poke around directly at bits and bytes in memory, etc. Obviously, C++ doesn't fit that bill; the closest language I've found is Haskell. Java's unchecked exceptions rule it out, though there are tools that can help with that.
If you want it to be easy to write code, you need a language that allows you to express what you want; that doesn't tie you down to rigid typing structures, or keep you fiddling with minutiae like memory management. This tends to mean a highly dynamic object-oriented language. Unsurprisingly, since this is the most common category for code to be in, this is the category with the most appropriate languages in it. Ruby and Python are two obvious ones. C++ is far too static, and keeps you far too immersed in low-level details to be useful here.
Of course, any given project is likely to consist of parts which fall into each of these three categories, which leads many people to seek a "compromise language" -- one which is "fast enough", "safe enough" and "easy enough". Ultimately, I believe such languages are always a waste of time. You will spend more time optimizing the bits that need optimizing, more time fixing bugs in the critical sections of the code, and much, much more time trying to design your software in such a way that you can actually build it, than if you were using the appropriate language for each part.
These languages are not difficult to tie together. All have easy ways to interact with C, which can be used as a thin layer of glue to stick them all together. The boundaries between the sections of code with different requirements tend to be reasonably well-defined, and you can therefore avoid crossing your language boundaries too often.
If you're using the right language for the job, your code will be as clear, concise, and well-designed as it's possible for it to be. To use the favorite vehicle analogy, you wouldn't try to use a Ford Ka as a personnel carrier in a war zone, and you wouldn't drive to the shops to get the groceries in an APC. Either might "work", but you'd be better off with two separate vehicles.
And please, don't try the argument that "it's easy for me to write C++" or "I don't waste time fighting C++'s memory management and lack of dynamicity" or "I don't make bugs these days"; it's well known that people are notoriously bad at analyzing their own productivity. There are simple studies and metrics that prove that programmers are more productive in more dynamic languages, and write safer code in safer languages.
You forgot to mention of few other important aspects...
- API support, e.g., it's no good to try and use python if you have to create bindings for a lot of external APIs. There are tools that automate this process, but sometimes its an issue.
- If you have to do lots of bit fiddling, C++ is alright. You can write safer code with its stronger type system than C, provided you know what you are doing.
- Fancy languages may have dependencies on 3rd party libs and APIs that may make using them on your platform of choice impractical.
Whether C++ is better than C depends on the job, and your point of view, and your skill. A novice can be lulled by the false promises of extra safety of C++. You can get that extra bit of (type) safety, but you have to work for it. An undisciplined C++ programmer probably creates very hard to find bugs.
The thing OSC is trying to say, is that time learning a new language is never wasted. There's tons of languages that let you do things easier and better than C/C++, and if you really need the extra performance, you can always fall back to C/C++ to do your gruntwork. And the "easier and better" part here isn't an opinion, it's a fact. One interesting revelation that may come to you when you code in higher level languages, is that you need that extra performance edge C will give you less often than you thought.
Now, that having said, I prefer to use Objective-C for GUI work on OS X, or some interpreted language for generic dabbling, but I do have large amounts of C++ code vested in a cross-platform (and multi-language) project.
I believe that C++ can be a convenient language to use, but you have to be aware of its limits, the limits of your understanding of C++ in particular, and the limits of your understanding of programming in general. C++ gives you lots of subtle ways to shoot yourself in the foot, and don't think you're special and it won't happen to you.
OneSadCookie
2007.03.13, 09:51 PM
You forgot to mention of few other important aspects...
- API support, e.g., it's no good to try and use python if you have to create bindings for a lot of external APIs. There are tools that automate this process, but sometimes its an issue.
Yes, "the best tool for the job" being a large third-party c++ library is one of the few good reasons for using it :)
Sometimes you can stick an abstraction level higher than the library, and avoid binding a large interface, in which case I generally think you should, but sometimes that's not feasible and you have to bite the bullet.
- If you have to do lots of bit fiddling, C++ is alright. You can write safer code with its stronger type system than C, provided you know what you are doing.
I disagree with this. C++'s type system *is* marginally more strict than C's, but not in ways I've often found to matter. I'd almost certainly write in C here, because there is far less opportunity for the code to run away.
- Fancy languages may have dependencies on 3rd party libs and APIs that may make using them on your platform of choice impractical.
Unfortunately, sometimes a problem on Windows. Seldom a problem on Mac OS X and Linux, and not a problem for the particular languages I listed in my prior post.
SOUCHAN
2007.06.04, 02:58 AM
I think we should all use D :-p
OneSadCookie
2007.06.04, 07:16 AM
I think we should all use D :-p
*runs screaming from the room*
FreakSoftware
2007.06.04, 03:53 PM
I think we should all use D :-p
*runs screaming from the room*
I read all 40 messages of an old thread just for that?!
Aye curumba...
vBulletin® v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.