2 Comments

Rekindling an Old Flame with C++11

The last time I looked at C++ was in 2002 when I was instrumental in convincing my co-workers to switch over to C#. Up until then, I had spent my entire college and professional career working with C++. That was eight long years. I don’t think I have used any one language for as long as I did C++.

Looking back at those times, I remember I couldn’t wait to part ways with my first language. It wasn’t that there was anything wrong with C++ (okay, maybe templates). It was just that there was this new world of other languages with all these fancy features that made my code much simpler.

After moving on to C#, I also explored other languages like Python, F#, Ruby, and Swift. Meanwhile, C++ remained the same with only minor updates in 1998 and 2003. Eventually, I said goodbye to C++ and never looked back.

Recently, I had to do some programming on Linux–rewriting some code that was written in C. Programming in C was not pleasant, and I desperately needed object-oriented constructs in the new code I was writing. I figured I would check out the changes they made with the new C++11 standard. I was pleasantly surprised, and I now have a new appreciation for C++. It still does not compare to the newer languages out there, but it does not look like the language I broke up with in 2002.

Favorite C++ Features

1. Auto

The auto keyword is similar to C# var where the type is inferred from the rvalue. I like not having to specify the type of the variable on the left side when it can be inferred from the right side of the expression.


// without auto
SomeType::SomeOtherType pObject = new SomeType::SomeOtherType();

// with auto
auto pObject = new SomeType::SomeOtherType();

2. Lambdas

Lambdas are a convenient way to write anonymous functions. Many times, you need to write quick throw-away functions without naming them. They have their roots in functional programming and are a part of many languages. They have the following form (some parts are optional):
[capture clause] (parameters) -> return-type {body}


// without lambdas
struct some_functor {
  void operator()(int) {
    // do something
  }
};

void func(std::vector& v) {
  some_functor f;
  std::for_each(v.begin(), v.end(), f);
}

// with lambdas
void func2(std::vector& v) {
  std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ });
}

3. New Range-Based for Loop Syntax

No more out-of-bounds indexing or zero-based indexing bugs.


void fun(vector& numbers)
{
  // index based for loop
  for(int i = 0; i < numbers.size(); ++i)
  {
    cout << numbers[i];
  }
  
  // range based for loop
  for (auto number : numbers)
  {
    cout << number;
  }

  // using a reference to allow us to change the value
  for (auto& number : numbers)
  {
    ++number;
  }
}

4. Initializers

C++11 has given a consistent means to initialize variables and lists. They even provide in-class initialization of non-static and non-const members.


//default initialization using empty brackets{}
int n{}; //n is initialized to 0
int *p{}; //initialized to nullptr
double d{}; //initialized to 0.0
char s[12]{}; //all 12 chars are initialized to '\0'

//explicit initialization
int n{4}; //n is initialized to 4
double d{2.3}; //initialized to 2.3
string s{"hello"};

//list initialization
vector myList {1,2,3,4,5,6};

//in-class initialization
//y is initialized to 8 in every instance of the class
class SomeClass
{
  public:
  SomeClass();
  private:
  int y{8};
};

These are some of my favorites, but there are so many more features added to the language. I would have liked to see the concept of interfaces introduced into the language. Getting the class definition just right to accomplish the same thing by using virtual base classes can be problematic.

For a more exhaustive list, you can read Bjarne Stroustrup’s explanation of the new standard.