Why I Love C++

C++ gets surprisingly little love these days. Some say it’s too low-level (the absence of garbage collection seems to be a popular complaint). Others say it’s not low-level enough. Again others claim it’s clumsy, bloated, and overly complex.

As you may have surmised from the title of this post, I do not agree. C++ is by far my favourite programming language. It’s not just that C++ is particularly well-suited for the projects I am currently using it for (Timetable Generator, and the backend of Project Flanders), although this is certainly true. More generally, I find C++ a pleasure to program in, more so than any other language I’ve used.

I will concede this much: if you don’t know what you’re doing, C++ is probably easier to misuse than other languages. However, in the hands of the experienced programmer, C++ can be a very versatile and powerful tool.

This post is the first of a series about programming in general and C++ programming in particular. The main purpose of the series is to share with you some of the things I’ve learned over the past few years, but I also hope to demonstrate the power of C++ in the process.

For now, I will start with an overview of why I hold C++ in such high esteem. I will try to stick to the high-level ideas, because I could go on and on about the specifics.

  • C++ combines the performance of C with the expressiveness of higher-level languages like Java. Many people see choosing a language as a tradeoff between performance and expressiveness. The prototypical choices are C on the one hand (fast because it’s close to the machine, but lacking high-level constructs that facilitate abstraction, like classes, inheritance, polymorphism, and generics/templates) and languages like Java, C#, or python on the other hand (slower because they are interpreted or run through a virtual machine, but having these high-level constructs). In C++, there is no tradeoff – you have both the performance of  C, and the convenience of high-level features. Unlike Java, C#, or python, C++ does not impose a performance overhead for high-level features.
    Consider garbage collection as an example, a feature shared by Java, C#, python, and many other “modern” languages. Garbage collection makes memory management much easier because it saves you from having to explicitly deallocate the memory that you have allocated. However, garbage collection invariably incurs a performance overhead in the languages that support it. On the other hand, in C++ you can use certain techniques (such as RAII) to achieve a level of automatic memory management that’s just as convenient as garbage collection, but with almost no overhead. Moreover, the C++ techniques for memory management generalize to the mangement of other resources, such as files, locks, and threads.
  • C++ has a strong, static type system, which means more errors get caught at compile time. Whenever I program in a dynamically-typed language such as python, I always marvel at how many mistakes I make that don’t get caught until the program is run. They are almost invariably the types of mistakes that in C++ would get caught at compile time. C++ makes your programs safer by catching errors as early as possible.
    The argument I made so far works in favour of any statically-typed language. However, C++’s type system has some features that set it apart from the type systems of other statically-typed languages like Java. First, C++ lacks the ability to do some type-unsafe things, like cast every object to type “Object” (OK, technically speaking, you can cast any pointer to void* in C++, but doing this is discouraged, while casting objects to Object is done routinely in Java). Second, C++ allows you to test a greater variety of conditions at compile-time (for example through static assertions and const-correctness).
  • C++ can be used to program in many different programming styles or paradigms. There are different programing paradigms, such as procedural programming, object-oriented programming, generic programming, and functional programming. Each has its strengths and weaknesses, and each is suitable for different purposes. Most languages are designed with one programming paradigm in mind, which means that if your problem domain has some areas that are suited for one paradigm, and some that are suited for another, you end up either using a language in a way that it wasn’t intended (which leads to awkward, hard-to-understand code), or using different languages for different components (which leads to repetition of common code). C++, on the other hand, is a multi-paradigm programming language that allows you to mix styles within the same program, so that you can use the style most suitable for each component, while staying in the same language.

I will give many examples that illustrate the power of C++ over the course of the next few posts, but as a teaser, I’ll start with the example that made me go “WOW”: Boost.Xpressive.

Do you use regular expressions? Do you ever think about what happens behind the scenes when you use a regular expression? What you type is a string representation of the regular expression. This string representation needs to be parsed, checked for syntax errors, and converted into an internal representation that can be used for fast matching (a finite automaton, as you might recall from your college theory courses). This process is called compiling the regular expression, because in many ways it is analogous to compiling source code into an internal representation that is suitable for fast execution (machine code).

Compiling a regular expression is expensive, yet in most languages, it needs to happen every time a program that uses a regular expression is run. If the regular expression is known at (the program’s) compile time (which most of the time it is), wouldn’t it be nice to be able to compile it at compile time, and check it for syntax errors at compile time?

Boost.Xpressive does exactly that. Instead of specifying a regular expression as a string, you specify it using C++ syntax elements that resemble the regex syntax. For example, to match a sequence of one or more letters or numbers, you would normally use the regular expression string:

"(\w|\d)+"

In Boost.Xpressive, you instead use the following (non-string) construct:

+( _w | _d )

Here, _d and _w are special regex constants, and the operators | and + are overloaded to build compound regexes from their operands. The syntax isn’t exactly the same (we are constrained by C++ syntax rules such as no backslash in identifier names, and the absence of a postfix + operator), but it is similar enough to be recognizable.

Here’s the punchline: in the process of compiling this line of code, the C++ compiler actually performs the compilation process for the regular expression, including syntax checking, and the only thing that goes into the compiled code is the final, internal representation of the regex. I invite you to show me another language that can do that!

Finally, a note on complexity. Writing a library like Boost.Xpressive is certainly not trivial – it involves advanced techniques like expression templates and template metaprogramming (both of which I’ll blog about in the future). But using the Boost.Xpressive library is not much more difficult than using regular expressions in other languages. And this brings us to perhaps the most distinctive property of C++: its core language features are versatile enough that many facilities that require language support (i.e. changes to the compiler, interpreter, or virtual machine) in other languages, can be implemented in C++ as a library. Just look at the Boost.Lambda library, for instance, which implements lambdas (anonymous functions constructed on the fly) without any language support (no, it’s not perfect, but it goes much further to emulate built-in lambdas than would be possible in other languages). When these libraries are well-designed, they can be just as easy to use as the corresponding built-in facilities in other languages. Of course, implementing such libraries is difficult, but so is implementing the built-in language features of other languages. The key difference is that extending a language with built-in features requires widespread concensus among the language’s community of developers, the cooperation of the entity in control of the language (e.g. Microsoft in the case of C#), and often a lengthy bureaucratic process. On the other hand, anyone can feel free to write a library that effectively extends the C++ language.

I hope I’ve given you a taste of the power and expressiveness of C++, and convinced you to at least keep an open mind when you hear people bashing it. I think it’s only fitting that I end with a quote by Bjarne Stroustrup, the creator of C++:

“There are only two kinds of programming languages: the ones people always bitch about, and the ones nobody uses.”

Advertisements

About botondballo

I am a recent graduate of the University of Toronto, with a degree in Computer Science. I currently work for Mozilla as a software engineer.
This entry was posted in c++, programming. Bookmark the permalink.

11 Responses to Why I Love C++

  1. Pingback: Resources for C++ Programmers « Perfection Beyond Reach

  2. Tim Locke says:

    If those are the reasons you like C++, you would probably like D even more than you like C++.

    • John says:

      Except that C++ works out of the box on iOS and Android devices today. D, not so much.

    • botondballo says:

      You’re right – according to the reasoning in this post, D is even better. In practice, though, I like C++ for one additional reason: the mature ecosystem around it, including countless libraries for just about anything you can imagine. D just doesn’t have that.

  3. > I invite you to show me another language that can do that!

    Rust’s regular expressions do this.

    That said, you’re right, not many do.

  4. Phil Miller says:

    Overall, well said. I think you understate your case a bit, when comparing C++ to Java in terms of expressivity. The rest of the article makes it very clear that C++ has expressive power that Java doesn’t really dream of, even years later.

  5. Adam Crume says:

    “C++ lacks the ability to do some type-unsafe things” is flat-out false. The fact that you can do `float f; *(int*)(void*)&f = 1;` (or aliasing through unions, or out-of-bounds array accesses, or NULL dereferencing, or reading free’d memory, or other bad things) shows that it is not type safe. The comparison to casting in Java is invalid, because something analagous like `String s = “”; Integer x = (Integer)(Object)s;` (or out-of-bounds array accesses, or null deferencing) will throw an exception, rather than result in undefined behavior. I’m not knocking C++; I’m just being pedantic. (While I’m being pedantic, dereferencing NULL in C++ is not guaranteed to result in a segfault. Not only is that system-specific, but it typically only works if you access memory near the start of the object. If you read from a large index of a NULL array, you might not get a segfault.)

  6. Ajk says:

    >Here’s the punchline: in the process of compiling this line of code, the C++ compiler actually performs the compilation process for the regular expression, including syntax checking, and the only thing that goes into the compiled code is the final, internal representation of the regex. I invite you to show me another language that can do that!

    Scala: macros and string Interpolation. You could even write normal regex, not some constant-and-operation-overload syntax

  7. Ryan says:

    C++ in Visual Studio targetting windows also allows for Mixed CLR. I recently had to write a Native Http Module in C++ for IIS7 and IIS8.

    In that module I came accross the need to parse MultiPart Form Data from the RequestEntityBody on the OnBeginRequest event. Not having much luck with C++ libraries to do it that were easy to compile I turned on CLR support for .Net 4+ and referrenced System.Net.Http.Formatting which has StreamContent in it for Parsing Mime Messages.

    So you can do something like this:

    //if the content ttype is not multipart… do nothing
    USHORT contentTypeLength = 0;
    char* rawContentType = (char*)request->GetHeader(“Content-Type”, &contentTypeLength);
    String^ contentType = gcnew String(rawContentType);
    if (!contentType->StartsWith(“multipart”, StringComparison::OrdinalIgnoreCase))
    return RQ_NOTIFICATION_CONTINUE;

    So in that I am using the native IIS api in HTTPServer.h to get the Content-Type header from the request, then I converted that to a .Net String “String^” .Net String type. Then I use .Net’s String->StartsWith to do a case insensitive compare.

    It was much easier to do that than raw C++ and since I already using .Net below it to parse the Mime Type on a Post Request with multipart form data, I didn’t stray away from using the CLR to save time.

    A lot of people never release you can do this with C++, but you can.

    You can write a C++ Dynamic Link Library that has Native exports with a Manifest.Def, __declspec, or even com registration while also have CLR code in that DLL that can be referenced by other .Net Assemblies or projects.

    .Net isn’t reaully a Virtual Machine language. All .Net is, is some proprietary MSIL byte code and it’s Assemblies have a special flag set in their PE File Format that says “I’m a .Net Assembly, I have MSIL in me”.

    When the windows loader loads a dll, it parses it’s PE File Format, sees the .Net flag set, and what CLR version it uses etc, then it Loads the .net framework into the process loading that dll, then Just In Time compiles all of that MSIL into X86 and loads the X86.

    When .Net assemblies are loaded into ram, they become Native Assemblies. So the entire .net framework is compiled to native code on the fly and loaded into the process, and any other .net assemblies being loaded with it.

    The trick is the .Net framework starts up a special sub program to garbage collect .Net objects, pointers etc. It also does a lot more Type Checking and function call validations etc etc and all of that is why it’s a bit slower than C++.

  8. Nice. I’m a bit late to the party here, but just wanted to say I was getting really really sick of all the C++ -bashing that goes on these days, so I looked up “I love c plus plus” and your post came up at the top of the search 🙂 !!

    I have “traditionally” been a C++ programmer, but have more recently immersed myself in some javascript front-end (react.js etc) and functional programming (currently learning Scheme and working through SICP) – all that stuff is great, too. I love it all.

    However, going back to C++ feels like catching up with an old friend. However, that old friend hasn’t exactly been idle, either. Since you wrote this article, the language has only gotten better and better ! ( with C++ 11, 14, 17 etc)

    I think the biggest failing of C++ (if it has one) is that it is TOO generous with features, and this means that you can write in a multitude of different paradigms and coding styles, resulting in each individual C++ programmer using their own personal subset of the huge smorgasbord of language features, which leads to lots of different “dialects”.

    Other than that, C++ is great.
    Long live C++ !!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s