Two Decades of Change For C++ and Me
Written by Lisa Cooper
As described previously, I recently spent two months revisiting C++ for the first time since the early 2000s. And you know what? It was pretty great. I've already covered why you'd want to learn C++ in this day and age (I was just as surprised as you are), but now I want to talk about the specific changes I noticed.
This article is only partially an excuse to metaphorically wave my cane from my porch at youngsters on my programming lawn. For fellow "old" timers (aka "Millennials" or even "Gen Xers"), I hope you'll enjoy this trip down memory lane as I grumble my way through modern advancements. For the new kids on the block, I hope you'll realize just how good you have it with C++20. :) If you want to follow along, pick up your own copy of C++ Programming 2nd Edition.
Chapter 1, figure 4. I've got Microsoft Visual Studio set up and I'm ready to roll with my first C++ program in two decades. I'm full of confidence because how hard can this be? Looking at the sample code for a basic circle calculator is like running into an old friend. After a brief stint with Python, it's so comforting to see variable declarations clearly spelled out. Then, look! There's my old friend cout! And string manipulation? Child's play.
Of course, having some knowledge quickly proves a trap. I'm tempted to skip ahead and not follow along with each example. "Yes, yes, I know this, that makes sense, of course I know how to add two variables, yes - wait, what?" Apparently I don't remember quite as much as I thought, or else things have changed.
Things have changed
As the examples get longer than a couple of lines, I find myself getting caught on small things in the IDE. Where is wordwrap? It's under tools, not window or view? Who decided that, and who can I complain to? But that's not a change to C++ itself, just Microsoft and its "new" ribbon UI.
Furthermore, some changes I'm embarrassed to realize aren't changes at all. For example, somehow I've forgotten the most basic function of all: main(). It was so basic to every program we wrote there was no need to memorize it; we just copy-pasted the same basic starter code from program to program. Still, somewhere a group of intro CS students is surely laughing at me.
But then come real surprises. "return EXIT_SUCCESS"? What sorcery is this? Turns out it's a "new" feature from C++11 that makes it clearer if your program worked or not than plain old "return" or "return 0." In fact, most "new" features that are treated as standard in this text will turn out to have been introduced in C++11. Seems that was either a very good year for C++ programmers or a very bad year, depending on your point of view.
Also on the list of "new to me" features: scope resolution operators and escape sequences, the latter of which sound much cooler than they actually are. I had trouble figuring out if these were truly new since 2001 or if my ancient high school textbook simply skipped over them. (It wasn't a very clear textbook, and the teacher's primary role was football coach, though he did his best.) In the end, I decide it doesn't matter if they're new or forgotten; I know them now and that's what's important. That's good, since scope resolution will play a crucial but understated part in nearly every subsequent program in the book.
Some additional shockers:
- Float and long types can now be declared simply by adding f or l after the values.
- The "auto" keyword means you don't have to know exactly what kind of variable you're using. What is this, Python?
- "Prior to C++11, it was a common practice to create unscoped enumerations." And yet I don't remember creating any at all...
- Stacks now refer to the top of the stack as the front and not the back, so, you know, that's weird.
- We can declare variables inside of if statements as of C++17. (But why did it take until 2017?)
- We now have override and final keywords for inheritance and overridden functions, which would have been handy during a certain group project I shudder to recall...
- Modules mean your code doesn't need to all be in a 5000-line main.cpp file now, which I want to resent but instead can only consider profoundly useful.
Where was this information 20 years ago?
My mind is blown in chapter 4 when I test ++x (prefix) vs x++ (postfix) and see the difference is exactly as described on the page. We exclusively used the postfix version in my day, and the notion that that wasn't good practice because it's not applied immediately has upended my world. Every for loop and counter I have ever written used i++. I spent a good hour trying to find something, anything on the internet that would claim this was a new feature and not simply something I didn't know, but no such luck. Similarly, namespaces are completely new to me, but turn out to be a defining feature between C++98... and C. It just may be possible that school didn't teach me everything there is to know.
Murach's C++ Programming likes to show me "best practices" and other useful ways to organize my code, none of which look like anything I've ever encountered before. Apparently hierarchy charts are a thing? Pretty sure best practice when I was in school was "just code stuff and poke at it until it works." The book further suggests that function code shouldn't be in header files to maintain a level of abstraction and make it easier for other programmers to use your classes. Excuse me, other programmers? Writing code for literally anyone but the TA to read? Seems "sus," as the kids today put it.
By the time I get to the entire chapter devoted to testing and debugging, I'm a little resentful. Strategies I devised through trial and error are described as if everyone should know and use them. I thought I'd invented debug tracing with cout statements. My console was filled with little snippets like "code reached this line," "this shouldn't be visible," and "kajlasjkd is this even running?" Clearly that could only be the work of mad genius, not a standard procedure, right? Not so, or else there are many more mad geniuses in the world than I thought.
In a similar vein, figuring out how to see variable values while stepping through code was a revelation for me back when. Meanwhile, new students are just given this information? I've never been a fan of gatekeeping, but the jealousy burns hot for a moment, or at least until I remember the younger brother I'm gifting this book to when my comp copies arrive. He's gonna love this chapter, or if he doesn't appreciate it properly he's gonna have to listen to me go on about why he should.
But as the chapters go on and the surprises keep coming, any jealousy is wiped away as my head starts spinning instead. Multiple inheritance? Excuse me? That seems ripe for abuse and errors, and the note that it sometimes leads to a "deadly diamond of death" is not reassuring. Friend functions? How is that even feasible? Did the ISO come up with that during drinks at some C++ conference after party? I'm in awe that they even work, let alone that they're calmly explained over the course of half a chapter. Can I code one now? Yes. Do I trust it's not magic? Not in a million years.
Coming to grips with being "legacy"
The first appearance of reference variables in chapter 6 I chalk up to me not remembering the exact vocabulary for pointers and dereferencing rather than anything new. Pointers took me a full month to grasp back in the day, largely thanks to the poor explanations given and my lack of understanding of how physical memory worked. So I assume references are just what we call pointers now, as the opposite of a "dereference" and carry on.
I finish the first section of the book still wondering when we're going to cover linked lists, but presumably that's not considered a "core skill" anymore thanks to faster processers. It's not until 10 chapters later I realize coding your own lists and trees with pointers is not only not "core" but is now considered a legacy skill for old, outdated systems. The imagined intro CS students are laughing at me again.
It gets worse. Fellow olds, brace yourselves: arrays are legacy now. The absolute backbone of any program more complicated than Hello World, gone the way of the dodo. Even the functions for determining array size are deprecated. On the bright side, this explains why I was so puzzled to see angle brackets (<>) instead of normal brackets () in use. The vindication is slight, however.
Sorts, meanwhile, are given attention that seems perfunctory to me after a full four years devoted to what felt like nothing but how to decide between nlogn functions for sorting vs n2 for adding elements and vice versa. I tell myself this is because there is a difference between computer science and computer programming, but it still hurts a little, especially when I learn every function we used to code by hand for our singly linked lists is now available via the Standard Template Library.
The legacy section isn't all bad news, however. Garbage collection, the new and delete functions, and deconstructers have all also gone out of fashion, and good riddance. I never could figure out when to use those, and de-allocating an int here and a string there always felt so ridiculous in the scope of the kind of programs we were making. Best of all, legacy skills are now worth $$$ on the job market if I'm ever persuaded to leave Murach Books. Take that, best modern practices and the STL!
Twenty++ years of change
And with that, I'm suddenly caught up on more than twenty years of C++ updates and changes. It feels as if everything is different, but that's almost certainly confirmation bias, as I paid no special notice to functions that worked exactly as I remembered them. Strings, for example, haven't changed much, rather like the sharks of C++ evolution.
Beyond the new features, the most glaring difference for me is that I didn't get to learn from a book as convenient as this one, which I admit also seems quite biased. Still, having Murach's C++ Programming on hand as a reference would have made many a homework assignment much, much easier. Fortunately, any younger relatives of mine who express even the slightest interest in programming won't have to go without.
I spare a moment to wonder if the next two decades will see yet more changes for the venerable language or if C++20 will prove the end of the line. I assume somewhere, deep in the bowels of ISO's headquarters, is an intern already compiling a list of fixes to be ready for the next released standard. I could confirm the truth of this for myself, of course – the internet is a marvelous thing – but the imagery is so much more fun.