C and C++ are the main programming languages for embedded computing and for a host of other application areas as well. C++ was developed by Bjarne Stroustrup and he was gracious enough to answer a few of my questions about C++ and its development. He not only developed the initial version of C++ but has been actively involved in updating through the latest standard, C++11. He has also taught and written about C++ with books like “Programming: Principles and Practice using C++.”

Wong: How did you get started designing C++?

Stroustrup: I needed a tool to help me on a project where I needed hardware access, high performance for systems programming tasks, and help with handling complexity. The project was to “split” a Unix kernel into parts that could run on a multi-processor or a high-performance local network. At the time (1979/80), no language could meet all three requirements, so I added Simula-like classes to C. The earliest designs added function argument checking and conversion (what later became C function prototypes), constructors and destructors, and simple inheritance. Interestingly, my earliest paper on “C with Classes” as it was called in the early years, used macros to implement a simple form of generic programming – later I found that didn’t scale and I had to add templates.

Over the next few years, my design (and implementation) was refined until the commercial release of C++ in 1985. Performance and hardware access was very important in the early years – as it still is. I considered it essential to be able to do everything C could do and to do it at least as efficiently. For example, early on, I found that to handle copy constructors, I had introduced a 3% overhead for returning structure values compared to C. I considered that unacceptable and by the end of the week the overhead was gone. Function call inlining was introduced to be able to handle interrupts in an embedded processor without the overhead of a function call and without forcing programmers to abandon classes to handle interrupts. The idea that facilities shouldn’t just be expressive and elegant, but also needed to be affordable in the most demanding applications was very important to me.

Wong: What were/are the major design goals for C++?

Stroustrup: A way of mapping C++ language features to machine facilities that is at least as direct and efficient as C’s plus abstraction mechanisms that allows programmers to express ideas beyond what I can imagine with no overhead compared to hand-crafted code.

This implies static (compile-time) type checking.

C++ was and is meant to be a tool for professionals and for people who takes programming seriously. It can and is used by novices, but the too often heard complaint that “C++ isn’t for everybody and not every project is easily done using C++” is based on a seriously miscomprehension. There can be no programming language that is perfect for everybody and for everything. C++ doesn’t try to be everything for everybody, but it is rather good at the tasks for which it was designed – mostly systems programming, software infrastructure, and resource-constrained applications. C++ dominates the fields where its strengths are needed. The fact that you can write a simple web app easier using JavaScript or Ruby does not bother me. Basically, C++ was not primarily designed for tasks of medium complexity, medium performance, and medium reliability, written by programmers of medium skills and experience. Obviously, it can be used for that and is widely used for that, but that’s not its areas of specific strength compared to many other languages.

I documented my design aims and the constraints on the design in my book “The Design and Implementation of C++” and in my two History of Programming Languages conference papers, but briefly, I aim for

  • zero overhead compared to hand-crafted code when using abstractions,
  • a machine model very similar to that of C,
  • an extremely flexible set of abstraction mechanism, and
  • static type safety.

The overall aim is to help produce better code for challenging real-world tasks, and “to make programming more pleasant for the serious programmer.” Obviously, I can’t get all of what I would like in every situation.

So C++ isn’t perfect. However, Despite innumerable attempts to displace it, C++ is still the best match for its stringent design criteria and for a huge range of real-world problems.

Wong: You have been working with the standard since it started. How has it changed over time and where is it headed?

Stroustrup: That’s hard to say. Formal standardization is a very hard and often tedious task. The people involved are usually clever and experienced, but they come from very diverse backgrounds and often represent major industrial interests, so constructing a consensus can be very difficult and is time consuming. Creating a consensus is essential because there is no way to force implementers to provide a faithful version of the standard and no way of forcing programmers to use novel features. Only by providing something almost universally agreed to be genuinely useful can we make progress. A standard committee is no place for single-issue fanatics. My estimate is that close to 100 organizations and maybe 300+ individuals are involved. That’s two to three times the numbers in the early years. We have had close to 100 people attending recent meetings.

Our plan is to issue a new standard with minor new features and corrections in 2014, C++14. This will almost certainly happen because we have already had national body votes on the changes and implementations of every new feature are available somewhere. I expect to be using C++14 in 2014. After that, there is a plan for C++17 in 2017. That will be a more major upgrade, so I can’t be quite as optimistic about the timing.

The ISO C++ standards committee has no resources (money, time, developers). The members actually have to pay $1200 a year to participate. If you don’t like what we do, don’t just complain. Don’t just say “I want a GUI library” or “there is no proper support for task-based concurrency” or whatever. We know that. Instead, come help us to get the work done right. We are always short of experienced application builders, so novel features have tendency to overly reflect the interests of implementers and library builders.

Wong: Many embedded designers choose to use C because “it is simpler and closer to the hardware” than C++. Do you think that complexity of C++ should be a deterrent to embedded designers?

Stroustrup: No. C isn’t simpler for C-style programming than C++ is, nor “closer to the hardware,” nor indeed more efficient. I have yet to see a program that can be written better in C than in C++. I don’t believe such a program could exist. By “better” I mean smaller, more efficient, or more maintainable. The myth that “C is simpler and more efficient” have caused (and causes) untold numbers of beginners to concentrate on obscure workarounds and difficult-to-master techniques, rather than learning how to use more powerful supporting features. Many then fall in love with their obscure and complex code, considering it a sign of expert knowledge. It is amazing what people can fail to learn when they are told that it is difficult and useless. The only reason I know of to use “plain C” rather than a suitable subset of C++ is lack of tool support on a given platform.

We can’t just blame the beginners/novices/students, though. The presentation and teaching of C++ has been a constant problem. Almost a decade ago, when I first was to teach programming to freshman engineering students, I looked at the textbooks using C++ and despaired. More precisely, I did not despair, I was furious! There were (and are) books teaching every little obscure detail of C before getting to the far-easier-to-use C++ alternatives, and deeming those alternatives “advanced” to scare off all but the most determined student. Seriously, how could a standard-library vector be as hard to use well as a built-in array? How could using qsort() be simpler than using the more general and efficient sort()? C++ provides better notational support and stronger type checking than C does. This can lead to faster object code.

Other books presented (and presents) C++ as a somewhat failed attempt to be a “pure object oriented programming language” and force most every operation into class hierarchies (a la Java) with lots of inheritance and virtual functions. The result is verbose code with unnatural couplings, and lots of casting. To add insult to injury, such code also tends to be slow.

As I said: if that’s C++, I don’t like it either! I responded by writing a textbook for college freshmen and determined self-learners: “Programming: Principles and Practice using C++.” It does not assume previous programming experience, though it has been popular with programmers wanting to know what C++ is about.

That book is a bit long for experienced programmers wanting a quick look at what  C++11 is like. For that I recommend “A Tour of C++” which presents all the major features of ISO C++ and its standard library in just 180 pages! C++11 is completely supported by Clang and GCC, and partially by Microsoft C++ and many other implementations. I fear that C++11 support is still be a bit spotty of less mainstream systems.

Wong: C++11 has added a number of features including lambdas and threading support. How has your view of features like these changed over time?

Stroustrup: I have wanted thread support in the standard for at least 15 years. Now I finally got it after having to have to use nice, but non-standard, thread libraries for decades. C++11’s contribution to concurrent programming is the memory model (now also adopted by C) and to make traditional threads-and-locks level programming portable and type-safe. That’s major. No macros and void**s are needed to share information and pass information between threads. For some, the facilities for lock-free programming are also important.

I have been concerned about lambdas for a while (maybe a decade), looking for a variant of the (inherently good) idea that would do more good than harm in the context of C++. The performance of the library versions were not sufficiently good, but the performance of the current implementations of C++11 lambdas (in current compilers) is as good as that of equivalent for-loop bodies. For example:

double sum = 0;

for (int i=0; i<v.size(); ++i) sum += v[i];    // array style

and

double sum = 0;

for (auto p = v.begin(); p!=v.end(); ++p) sum += *p;   // pointer style

and

double sum = 0;

for_each(v.begin(),v.end(), [&](double d) { sum += d; });   // algorithm style

These alternatives now run at exactly the same speed on all major C++ compilers. That is, we can now choose between those styles based on aesthetics, maintainability, etc.

There are quite a few places where I use lambdas in preference to alternatives. For example:

sort(v, [](const string& a, const string& b) { return a>b; });           // sort in reverse order

That said, lambdas is a new and powerful feature. Such features are always overused until the community learns what pays off in the long run. In my opinion, it is often worthwhile to separately define a function or a function object so that the operation can have a specific name, can be used from multiple places in a program and where there is space for a helpful comment. Lambdas can easily become and exercise in write-only code.

This is not the place to teach C++11, but let me give just one example:

template<typename C, typename V>

vector<Value_type<C>*> find_all(C& cont, V v)  // find all occurrences of v in cont
{
    vector<Value_type<C>*> res;

    for (auto& x : cont)
        if (x==v)
            res.push_back(&x);
    return res;
}

Here, I use several new features. The new for-loop, a range-for loop, is read “for all x in cont” and simplifies traversing the container cont. The auto& x declaration says that the type of x should be a reference to the type of the elements in the initializer of x, that is, a reference to the type of elements in cont. The loop collects the addresses of all occurrences of v in cont in the vector of pointers res.

So far, the new features here have been merely “syntactic sugar,” but these are rather nice and useful notational improvements. The real novelty here is the return statement: Note that I return a potentially huge vector by value. In C++98, that would typically cause the copy of all elements of res, potentially many thousands of elements. That would be a serious performance bug. In C++11, vector has a “move constructor,” so that rather than copying elements, the representation of res (merely three pointers) is “stolen” for use in the caller and an empty vector is left behind. After all, we are just about to return from find_all() and won’t be able to use res again. Thus, returning a vector by value costs at most six word assignments independently of the number of elements.

Move constructors is a simple facility available to every programmer and used by all standard-library containers implemented as handles. This allows us to return large objects from a function without messing around with memory management (explicitly) using pointers and free store.

We can test find_all() like this:

void test()
{
string m {"Mary had a little lamb"};

for (const auto p : find_all(m,'a'))            // p is a char*
    if (*p!='a')
        cerr << "string bug!\n";

vector<string> v {"Mary”, “lamb", “Mary”, “mary”, “wolf”};

for (const auto p : find_all(v,”Mary”))    // p is a string*
    if (*p!=”Mary”)
        cerr << "vector<string> bug!\n";
}

Feel free to compare this to a hand-crafted version without templates or C++11 features.

For more information, read “A Tour of C++.” For all the details see “The C++ Programming Language (Fourth Edition).”

Wong: What common mistakes do you see new C++ developers making?

Stroustrup: They think they have to choose between “efficiency” and elegance, so they either stick to a small low-level subset (“for efficiency”) or build bloated “do-everything” designs (deeming those elegant). My ideal is for the most efficient code also to be the most elegant. That happens when you have a perfect fit between a problem and a solution. Obviously, you can’t always achieve that and you rarely achieve it at the first try, but it happens often enough for the ideal to be of practical relevance.

Before dismissing C++ features, such as classes and templates, for demanding tasks, learn the basics of their use and try them out. Measure, rather than guessing about performance! Do not feel obliged to craft huge hierarchies or write complicated template meta-programs. Some of the most powerful C++ features are quite simple and leads to good object code. One of the best ways to get efficient code is to write simple source code.

Wong: What do you like to do for fun?

Stroustrup: Travel to interesting places, run, take photographs, listen to music, read (literature and history), spend time with family and friends. Of course, some of my programming is great fun also, but I guess you weren’t asking about work. Research and advanced system building is fun. As they say “I can’t believe we are getting paid for doing this!”