We finally get to the good stuff. The discussion below contains a lot of the reasons I wanted to do this write-up in the first place.
1:00:00 Let’s Make an Array Type.
This might seem trivial to a lot of people. This is basically just a fix for the std::vector<int> name; problem I discussed earlier in this series. We use arrays everywhere in our code. We’re constantly building lists of data. C++ offers tons of ways to do this, and somehow they all suck.
The lazy way:
That gives us space to store 10 things, which sucks if the program suddenly needs 11. The array is of fixed size. So let’s do it the “right” way:
1 2 3 4 5
int* things; things = (int*)malloc (sizeof (int)*10); //(A bunch of stuff happens. And then a long time later... free (things);
We allocate the memory ourselves. If we need more, we can allocate more. But we need to ask for the memory ourselves, we can’t use more than we asked for, and we can’t forget to free it. It’s prone to mistakes and takes an unreasonable level of work and care for what should be a simple, low-stress task.
And the bestNot the best in all cases, but certainly the best for simple lists of unknown size. way to do it:
That’s actually the
best least awful solution so far. This makes a list that can grow or shrink or be re-ordered whenever you like and the compiler will worry about all that stupid memory management crap for you. But because this feature was bolted onto the languageDoes the standard library count as “part of the language”? I honestly don’t know. so late in the lifespan of C/C++, the syntax is strange, verbose, and ugly. If you make a mistake it will sometimes spew pages of gibberish error messages at you over a simple misplaced symbol.
(Nitpick shield: There are a LOT more ways to store data. Linked lists, hash tables, whatever. But they’re kind of specialized and have other tradeoffs. These three are enough for us to consider right now.)
Blow is proposing we take this simple idea and express it in a simple way. That’s it.
I’m not totally sold on the thing where he moves the brackets around and adds exclamation marks four minutes later. I can’t tell if I don’t like it because there’s something wrong with it or if I don’t like it because it’s unfamiliar. But whatever. The important point is that a language could do better than we’re doing now. (And lots of modern languages do.)
1:14:00 NO HEADER FILES
C programs are nothing more than text files. But you generally don’t want to put your whole program into one text file. It would be gigantic and you’d never be able to find anything. So for the sake of organization, we put related ideas into the same file. All the code for handling space marines goes in SpaceMarine.cpp and the code for rockets goes in Projectiles.cpp and the code for sound effects goes in Audio.cpp. Or whatever. You can organize it however you like.
So the functions in these files need to talk to each other. Maybe a rocket, when it detects it’s hit a space marine, needs to make them explode. So it will call SpaceMarineExplode (). So the compiler is working its way through Projectiles.cpp and it sees the use of SpaceMarineExplode (), but it doesn’t know what to do with it. It hasn’t read the space marine fileIT actually reads each file in isolation. It’s… not a great system.. It doesn’t know that SpaceMarineExplode () exists. Maybe I just broke up with my girlfriend Marnie, and in a fit of distress, teen angst, and Freudian slippage I’ve accidentally typed SpaceMarnieExplode (). How is the compiler supposed to know that one is correct and the other is wrong? What about when the phone rings, I hope it’s her, then realize it can’t be her, and won’t ever be her ever again, and I go face-down on the keyboard and as I’m sobbing snotty tears I manage to type kbggggggytyutgiiiiiiiii? How does the compiler know that SpaceMarineExplode () is a valid function and kbggggggytyutgiiiiiiiii isn’t?
Well, in C we have “prototypes”. It’s just a single line of textYou HOPE. that says, “SpaceMarineExplode () is a thing. “It’s not in THIS text file, but I’ll define it in one of the other text files.” It’s a promise to the compiler that the thing will show up later.
I don’t know enough about the history of the language, but I imagine this was done because C was invented in 1968 and computers had very little memory, they were very slow, and disk access was glacial. Compiling would take a long time. The last thing you wanted was for the compiler to have to read ALL THOSE TEXT FILES THERE MUST BE NEARLY 100 KILOBYTES OF THEM ARE YOU MAD and create an inventory of everything, and then go through them all AGAIN to do the actual compiling.
To avoid this, we put all those prototypes in another text file called the header file. Like SpaceMarine.h. Then Projectiles.cpp can #include<SpaceMarine.h> which will bring in all those prototypes. Basically, we’re manually doing that messy “inventory” step manually. By typing things. Instead of letting a computer do it.
This is a monumentally horrible way of doing things, and has been for decades. It gets even more fun when one header file needs to read another. So SpaceMarine.h will #include Weapons.h and that file will include Projectiles.h, which turns around and includes SpaceMarine.h, which is the file it’s already trying to compile. So the compiler goes crazy, locks up, or (if you’re using a modern compiler because you’re not a savage) gives you a cryptic error that lets you know about the circular reference without telling you what it is. There are ways to protect against this, which involves stupid boilerplate code to the effect of “If you’ve read this file before, don’t read it again”, which probably seems like the kind of busywork that the compiler could probably sort out on its own if this paradigm hadn’t been designed a year before The Beatles broke up.
So header files suck. They dump onto programmers really tedious busywork that some sort of compiler could easily take off our hands. Other languages don’t waste your time with this.
So that’s the presentation. Hope you enjoyed it. Or found it educational. Or whatever. I have to go back to
complaining about using C++ to get work done.
 Not the best in all cases, but certainly the best for simple lists of unknown size.
 Does the standard library count as “part of the language”? I honestly don’t know.
 IT actually reads each file in isolation. It’s… not a great system.
 You HOPE.
Crysis 2 has basically the same plot as Half-Life 2. So why is one a classic and the other simply obnoxious and tiresome?
Bad and Wrong Music Lessons
A music lesson for people who know nothing about music, from someone who barely knows anything about music.
A Telltale Autopsy
What lessons can we learn from the abrupt demise of this once-impressive games studio?
The Best of 2011
My picks for what was important, awesome, or worth talking about in 2011.
Denuvo and the "Death" of Piracy
Denuvo videogame DRM didn't actually kill piracy, but it did stop it for several months. Here's what we learned from that.