Daily C++11: introduction, nullptr, template closing characters
C++11 is really a step forward in the history of my second favorite programming language (after C, of course). From 1998 there wasn’t much evolution in the language; not that a language needs evolution as a constant, but for sure, but C++ is far from perfect.
Probably the experience of the last years showed programmers moving from C++ to Java and C#. There were a few reasons to do this.
First is automated garbage collection. I know that many programmers dropped the ball on C++ because it was too easy to have a memory leak. However, this was not necessarily an issue. Smart pointers were available, but not very convenient to use – there was no standardization, and everyone used their own thing.
The C legacy is a double-edged sword. The good part is that programmers get to reap all the benefits of the C language: maximum efficiency, great flexibility. The bad part is that habits born in the C world tend to make the C++ programmers less productive; not only when it comes to raw code writing but also when it comes to library design; C++ libraries tend to spend a lot of time in discussing who frees what and when and how, and that’s just one example.
Sure, ‘boosters’ have always existed. For anyone willing to include a 160+MB source tree in their sources, ‘boost’ library (and not only) offers complex solutions for complex problems. But learning what happens in 160+MB of sources and understanding that complex framework makes adoption too hard.
I personally had huge problems adopting the STL. STL was, from my point of view at that time, too complex, and too inefficient. I was always a C programmer and I am not afraid to admit it; yet I also liked the encapsulation part of C++. Then, it was the templates. Only later was the STL: but it was not love at first sight; it was hatred for the alternatives (and got tired of writing my own vector and string class).
But the real drawback for me it was that it was TOO much to learn, and there was too much to learn the same thing over and over again. You have std::string, CString, CCOMString, QString. And then again you have the performance driven C standard functions from string.h which, now, can be accessed through <cstring>. Of course, the trick is to use the namespace version of the calls. Which adds to the confusion, of course.
Now, C++11 doesn’t change this much. You can always write a new C++ string class. You can probably build a new framework – and most people did because they lacked the necessary functionality. Yet, with the new C++ standard you will be less compelled to write it, as the standard offering may be better (even if limited) for your development.
The aim of C++11 is productivity. The new standard adds new semantics, new library enhancements, lambda functions, initializers: all to improve the productivity of the C++ user. But this comes with a cost: more has to be learned, and some bad corners of C++ must be avoided. For example, it’s still OK to free your memory; it’s better to do memory management via smart pointers. It’s still OK to use thread libraries; it is better to use the new threading support in the standard library.
For the syntactic sugar lovers, improvements have been made there too. The ‘auto’ will confuse some programmers, while others will love it. The range based loops will make code clearer and easier on the eye. Initialization syntax is improved, while lambda expressions will make everyone’s head spin. So I will guide you through all these improvements, and guide myself in the process too: because I will study it and write you about it as I do it.
Today, two simple features, to make sure ‘we learn something new’. 🙂
The NULL pointer was always a special thing. It’s the constant 0, and in C the standard headers always had the NULL macro to fix this – to discern from the 0 integer value, NULL was defined as ((void *)0). This is not a problem in C. Automatic cast from void * is done, nobody complains.
In C++, however, there is such a thing as overloading a function. So say you have two calls:
void init(char *name);
void init(int size);
calling init(NULL) will make the compiler unsure about what you want to call. First, if you don’t use the standard C NULL definition (that might be in a header you don’t include), you might be tempted to use 0 for NULL, which actually calls the second function. If you use the standard NULL definition, you’ll get an error, because there is no void init(void *); so you’ll do something like: init ((char *) NULL); . This is why, in fact, C++ defines the NULL pointer as 0.
nullptr fixes this issue. Now part of the language, nullptr is guaranteed to be a pointer, will convert to any pointer type, and it will NOT convert to integral types with the exception of bool. Why bool? Well, because you still want to test the pointer like:
if (nullptr) ;
or bool b = nullptr; if (b) ;
So use nullptr from now on. This should be compatible with NULL, and in the future, probably, NULL will be defined as nullptr (if it’s not already).
Template closing characters
The C++03 standard was quite strict in interpreting >> as shift operators. This was not so fun when you were writing template code that was a bit more complex. Take, for example, the declaration of a jagged array.
This will be an error in C++03 because of the closing characters. To fix this one would avoid it by creating an intermediate type for std::vector<int> or (a bit more silly) by placing a space between the last two brackets. This is really against the philosophy of C and C++; C++11 fixes that.
So, to make it short, always use nullptr instead of NULL in new C++ code and now you may use the template closing characters without silly spaces.