Back to Index

Bjarne Stroustrup: C++ Zero-Overhead Principle and Object-Oriented Programming


Transcript

C++ is an object-oriented programming language that creates, especially with its newer versions, as we'll talk about, higher and higher levels of abstraction. So how do you design, let's even go back to the origin of C++, how do you design something with so much abstraction that's still efficient and is still something that you can manage, do static analysis on, you can have constraints on, they can be reliable, all those things we've talked about.

To me, there's a slight tension between high-level abstraction and efficiency. That's a good question. I could probably have a year's course just trying to answer it. Yes, there's a tension between efficiency and abstraction, but you also get the interesting situation that you get the best efficiency out of the best abstraction.

And my main tool for efficiency, for performance, actually is abstraction. So let's go back to how C++ got there. You said it was an object-oriented programming language. I actually never said that. It's always quoted, but I never did. I said C++ supports object-oriented programming and other techniques. And that's important because I think that the best solution to most complex, interesting problems require ideas and techniques from things that have been called object-oriented, abstraction, functional, traditional C-style code, all of the above.

And so when I was designing C++, I soon realized I couldn't just add features. If you just add what looks pretty or what people ask for or what you think is good, one by one, you're not going to get a coherent whole. What you need is a set of guidelines that guides your decisions.

Should this feature be in or should this feature be out? How should a feature be modified before it can go in and such? And in the book I wrote about that, the design evolution of C++, there's a whole bunch of rules like that. Most of them are not language technical.

There are things like don't violate static type system because I like static type system for the obvious reason that I like things to be reliable on reasonable amounts of hardware. But one of these rules is the zero overhead principle. The what kind of principle? The zero overhead principle. It basically says that if you have an abstraction, it should not cost anything compared to write the equivalent code at a lower level.

So if I have, say, a matrix multiply, it should be written in such a way that you could not drop to the C level of abstraction and use arrays and pointers and such and run faster. And so people have written such matrix multiplications and they've actually gotten code that ran faster than Fortran because once you had the right abstraction, you can eliminate temporaries and you can do loop fusion and other good stuff like that.

It's quite hard to do by hand and in a lower level language. And there's some really nice examples of that. And the key here is that that matrix multiplication, the matrix abstraction allows you to write code that's simple and easy. You can do that in any language. But with C++, it has the features so that you can also have this thing run faster than if you hand coded it.

Now people have given that lecture many times, I and others, and a very common question after the talk where you have demonstrated that you can outperform Fortran for dense matrix multiplication, people come up and say, "Yeah, but that was C++. If I rewrote your code in C, how much faster would it run?" The answer is much slower.

This happened the first time actually back in the 80s with a friend of mine called Doug McElroy who demonstrated exactly this effect. And so the principle is you should give programmers the tools so that their abstractions can follow the zero-overhead principle. Furthermore, when you put in a language feature in C++ or a standard library feature, you try to meet this.

It doesn't mean it's absolutely optimal, but it means if you hand code it with the usual facilities in the language, in C++, in C, you should not be able to better it. Usually you can do better if you use embedded assembler for machine code for some of the details to utilize part of a computer that the compiler doesn't know about.

But you should get to that point before you beat to the abstraction. So that's a beautiful ideal to reach for. And we meet it quite often. Quite often. So where's the magic of that coming from? Some of it is the compilation process, so the implementation of C++. Some of it is the design of the feature itself, the guidelines.

So I've recently and often talked to Chris Ladner, so Clang. Just out of curiosity, is your relationship in general with the different implementations of C++ as you think about you and committee and other people in C++, think about the design of new features or design of previous features? Even trying to reach the ideal of zero overhead, does the magic come from the design, the guidelines or from the implementations?

And not all. You go for programming technique, program language features and implementation techniques. You need all three. And how can you think about all three at the same time? It takes some experience, takes some practice and sometimes you get it wrong, but after a while you sort of get it right.

I don't write compilers anymore, but Brian Kernighan pointed out that one of the reasons C++ succeeded was some of the craftsmanship I put into the early compilers. And of course I did the language design and of course I wrote a fair amount of code using this kind of stuff.

And I think most of the successes involves progress in all three areas together. A small group of people can do that. Two, three people can work together to do something like that. It's ideal if it's one person that has all the skills necessary, but nobody has all the skills necessary in all the fields where C++ is used.

So if you want to approach my ideal in say concurrent programming, you need to know about algorithms from concurrent programming. You need to know the trigger of lock-free programming. You need to know something about the compiler techniques. And then you have to know some of the application areas where this is, like some forms of grammar, graphics or some forms of what we call a web-serving kind of stuff.

And that's very hard to get into a single head, but small groups can do it too. ------------------------------fe4f6f6f6f6-- ------------------------------fe4f6f6f6f6-- ------------------------------fe4f6f6f6f6-- ------------------------------fe4f6f6f6f6--