/ Partnerships

Talking C++: An Interview with Bjarne Stroustrup

bjarne_stroustrup

Bjarne Stroustrup is a Technical Fellow and Managing Director at Morgan Stanley in New York City and a Visiting Professor at Columbia University. He's also the creator of C++.

Mariel and I, authors of Codecademy’s Learn C++ course, recently got a chance to catch up with Dr. Stroustrup and chat about upcoming changes, the “golden years” of Bell Labs, and to ask him questions from Stack Overflow. Enjoy.


Let’s rewind a little bit. There are a lot of stories floating around about how you created C++ at Bell Labs in ’79. Can you give us a window to that world—what brought you to Bell Labs? What was life like there?

In the 1970s, 80s, and 90s, Bell Labs Computer Science Research Center was the greatest place on earth for practical computer science—and some theoretical CS also. There was no place like it.

Towards the end of my Ph.D. studies in Cambridge, I called someone from Bell Labs who had visited to give a talk and asked if they had any jobs. They didn’t but I was welcome to stop by and present my work. I did and after days of grueling interviewing, it turned out that they had a position after all.

bell-labs

Bell Labs Computing Sciences Research Center, Murray Hill, New Jersey (Source)

The number of really bright, knowledgeable, and creative people was extraordinary. Many were also extremely patient listeners and helpful in developing new ideas and systems. Whatever you wanted to know about, you’d find an expert nearby.

The building in Murray Hill where the core research was located had about 1000 PhDs in a variety of scientific and engineering fields. Researchers were given a lot of freedom to choose what to work on—much more than was the case in most other places, then and now.

All that was required was that eventually, you produced something great. That sounds cushy, but the ideas of what constituted “great” was quite demanding; to quote the Wikipedia:

“Researchers working at Bell Labs are credited with the development of radio astronomy, the transistor, the laser, the photovoltaic cell, the charge-coupled device (CCD), information theory, the Unix operating system, and the programming languages C, C++, and S. Nine Nobel Prizes have been awarded for work completed at Bell Laboratories.”

Was there an “aha” moment when you realized C++ could be game-changing for the software/hardware industry?

Not really. I was too busy working on C++ and using it.

The closest must have been in 1989 when representatives from IBM and HP turned up in my office at Bell Labs and insisted that “you really would like to” standardize C++ in an ANSI committee.

Or maybe when the ACM History Of Programming Languages (HOPL) conference suggested I write a paper on C++ for their conference. Even then, I think I underestimated the impact of C++ and the programming techniques it enabled.

Bjarne Stroustrup and Sonny Li

Talking C++ in New York City. 📸: Mariel Frank.

If you could go back in time and change one thing about the original implementation of C++, what would it be?

I don’t have a time machine and I shouldn’t try to second-guess 1983-vintage Bjarne—he knew the conditions at the time better than I do now, and any significant change probably wouldn’t have fitted in the 1MB memory I had to work with, and if it had maybe I wouldn’t have been able to port the compiler to an early 640MB Windows machine.

But if I could and if realities of compatibility didn’t get in the way, I’d like to eliminate the implicit narrowing and value-changing conversions. They are logically wrong and major sources of errors. For example:

int x = -2000;

char ch = x;       // bad

unsigned u = x;    // bad

Are there any applications or uses of C++ that you have been especially surprised or excited about?

What amazed me most was the range of applications: from rice cookers to space rockets. It is humbling to realize that just about wherever you look there is C++ involved: cars, movies, games, medicine, finance, computers, farming, etc.

I find it most gratifying that C++ has been used in science: the human genome project, the fundamental physics research at CERN and elsewhere, and the Mars Rovers. It feels great to have made a contribution, however small.

Learn C++ is currently one of the top courses on Codecademy, and the language is still taught in schools and used in industries around the world. From your perspective, why should someone learn C++ in 2020?

C++ is one of the most useful languages there is. That should be a sufficient reason. Someone wanting to be a professional should know a few languages—not just one—and C++ is a good one to know for work that requires performance and reliability.

Another way of looking at it is that C++ is very widely used in finance, games, telecom, electronics, and manufacturing. See JetBrains’ blog post and my "C++ Applications" page and try to guess why a language without marketing is so widely-used.

In my opinion, the best reason for learning C++ is that it gives you insights into a variety of programming and design techniques that are applicable in a wide variety of languages.

What tips would you give to a budding programmer?

Programming can be fun, but it is not all fun and games. Our civilization depends on good software.

Whatever you are interested in, there will be a use for programming: literature, automobile production, history, coffee making, wind and solar energy, movie making, rocket science, farm management, medicine, science, engineering, and so much more.

Bjarne Stroustrup

📸: Mariel Frank.

You might eventually be able to make a significant contribution to whatever field you find important or interesting! To do that you’ll have to know the field and the tools and techniques of software development. Be sure you learn about fundamentals, such as data structures and how machines work.

Don’t get overwhelmed, and don’t think you will be an expert in just a few weeks. Think of how long it takes to learn to speak a natural language, how long it takes to become a good athlete, and how long it takes to learn to play an instrument well enough for someone who isn’t your mother to want to listen to.

Think about how much fun you can have along the way to reach such mastery and how many friends you might make along the way. Some of the nicest people work with software.


Here’s the part that we’ve been waiting for. (🥁…)

We’ve gathered the highest-voted C++ questions on Stack Overflow. The world wants to know your take on them.

🥇 Why is processing a sorted array faster than processing an unsorted array?

Why is processing a sorted array faster than processing an unsorted array?

Note: This question is the #1 highest voted question on Stack Overflow of all time. 😱

That sounds like an interview question. Is it true? How would you know? It is a bad idea to answer questions about efficiency without first doing some measurements, so it is important to know how to measure.

So, I tried with a vector of a million integers and got:

Already sorted  32995 milliseconds
Shuffled        125944 milliseconds

Already sorted  18610 milliseconds
Shuffled        133304 milliseconds

Already sorted  17942 milliseconds
Shuffled        107858 milliseconds

I ran that a few times to be sure. Yes, the phenomenon is real. My key code was:

void run(vector<int>& v, const string& label)
{
    auto t0 = system_clock::now();
    sort(v.begin(), v.end());
    auto t1 = system_clock::now();
    cout << label 
         << duration_cast<microseconds>(t1 — t0).count() 
         << " milliseconds\n";
}

void tst()
{
    vector<int> v(1'000'000);
    iota(v.begin(), v.end(), 0);
    run(v, "already sorted ");
    std::shuffle(v.begin(), v.end(), std::mt19937{ std::random_device{}() });
    run(v, "shuffled    ");
}

At least the phenomenon is real with this compiler, standard library, and optimizer settings. Different implementations can and do give different answers. In fact, someone did do a more systematic study (a quick web search will find it) and most implementations show that effect.

One reason is branch prediction: the key operation in the sort algorithm is “if(v[i] < pivot]) …” or equivalent. For a sorted sequence that test is always true whereas, for a random sequence, the branch chosen varies randomly.

Another reason is that when the vector is already sorted, we never need to move elements to their correct position. The effect of these little details is the factor of 5 or 6 that we saw.

Quicksort (and sorting in general) is a complex study that has attracted some of the greatest minds of computer science. A good sort function is a result of both choosing a good algorithm and paying attention to hardware performance in its implementation.

If you want to write efficient code, you need to know a bit about machine architecture.

🥈 What is the --> operator in C++?

What-is-the------operator-in-C---

That’s an old trick question. There is no “-->” operator in C++. Consider:

if (p-->m == 0) f(p);

It certainly looks as if there is a —-> operator and by suitable declaring p and m, you can even get that to compile and run:

int p = 2;
int m = 0;
if (p-->m == 0) f(p);

That means: see if p-- is greater than m (it is), and then compare the result (true) to 0. Well true != 0, so the result is false and f() is not called. In other words:

if ((p--) > m == 0) f(p);

Please don’t waste too much time on such questions. They have been popular for befuddling novices since before C++ was invented.

🥉 The Definitive C++ Book Guide and List

The-Definitive-C---Book-Guide-and-List

Unfortunately, there is no definite C++ book list. There can’t be one. Not everyone needs the same information, not everyone has the same background, and C++ best practices are evolving.

I did a search of the web and found a bewildering set of suggestions. Many were seriously outdated and some were bad from the start. A novice looking for a good book without guidance will be very confused!

You do need a book because the techniques that make C++ effective are not easily picked up from a few blogs on specific topics—and of course blogs also suffer from mistakes, being dated, and poor explanations. Often, they also focus on advanced new stuff and ignore the essential fundamentals.

I recommend my Programming: Principles and Practice Using C++ (2nd Edition) for people just beginning to learn to program, and A Tour of C++ (2nd Edition) for people who are already programmers and need to know about modern C++. People with a strong mathematical background can start with Peter Gottschling‘s Discovering Modern C++: An Intensive Course for Scientists, Engineers, and Programmers.

Once you start using C++ for real, you need a set of guidelines to distinguish what can be done and what is good practice. For that, I recommend the C++ Core Guidelines on GitHub.

For good brief explanations of individual language features and standard-library functions, I recommend www.cppreference.com.

#4. What are the differences between a pointer variable and a reference variable in C++?

What-are-the-differences-between-a-pointer-variable-and-a-reference-variable-in-C---

To learn more about references and pointers, check out Learn C++. 😊

Both are represented in memory as a machine address. The difference is in their use.

To initialize a pointer, you give it the address of an object:

int x = 7;
int* p1 = &x;
int* p2 = new int{9};

To read and write through a pointer we use the dereference operator (*):

*p1 = 9;      // write through p1
int y = *p2;  // read through p2

When we assign one pointer to another, they will both point to the same object:

p1 = p2;      // now p1 p2 both point to the int with the value 9
*p2 = 99;     // write 99 through p2
int z = *p1;  // reading through p1, z becomes 99 (not 9)

Note that a pointer can point to different objects during its lifetime. That’s a major difference from references. A reference is bound to an object when it is created and cannot be made to refer to another.

For references, dereferencing is implicit. You initialize a reference with an object and the reference takes its address.

int x = 7;
int& r1 = x;
int& r2 = *new int{9};

Operator new returns a pointer, so I had to dereference it before assigning using it to initialize the reference.

To read and write through a reference, we just use the reference’s name (no explicit dereferencing):

r1 = 9;        // write through r1
int y = r2;    // read through r2

When we assign one reference to another, the value referred to will be copied

r1 = r2;       // now p1 and p2 both have the value 9
r1 = 99;       // write 99 through r1
int z = r2;    // reading through r2, z becomes 9 (not 99)

Both references and pointers are frequently used as function arguments:

void f(int* p)
{
    if (p == nullptr) return;
    // ...
}

void g(int& r)
{
    // ...
}

int x = 7;
f(&x);
g(x);

A pointer can be the nullptr, so we have to consider whether it points to anything. A reference can be assumed to refer to something.

#5. How do I iterate over the words of a string?

How-do-I-iterate-over-the-words-of-a-string-

Use a stringstream, but how do you define “a word”? Consider “Mary had a little lamb.” Is the last word “lamb” or “lamb.”? If there is no punctuation, it is easy:

vector<string> split(const string& s)
{
    stringstream ss(s);
    vector<string> words;
    for (string w; ss>>w; ) words.push_back(w);
    return words;
}

auto words = split("here is a simple example");  // five words
for (auto& w : words) cout << w << '\n';

or just:

for (auto& w : split("here is a simple example")) cout << w << '\n';

By default, the >> operator skips whitespace. If we want arbitrary sets of delimiters, things get a bit more messy:

template<typename Delim>
string get_word(istream& ss, Delim d)
{
    string word;
    for (char ch; ss.get(ch); )  // skip delimiters
        if (!d(ch)) {
            word.push_back(ch);
            break;
        }
    for (char ch; ss.get(ch); )  // collect word
        if (!d(ch))
            word.push_back(ch);
        else
            break;
    return word;
}

The d is an operation telling whether a character is a delimiter and I return "" (the empty string) to indicate that there wasn’t a word to return.

vector<string> split(const string& s, const string& delim)
{
    stringstream ss(s);
    auto del = [&](char ch) { for (auto x : delim) if (x == ch) return true; return false; };

    vector<string> words;
    for (string w; (w = get_word(ss, del))!= ""; ) words.push_back(w);
    return words;
}

auto words = split("Now! Here is something different; or is it? ", "!.,;? ");
for (auto& w : words) cout << w << '\n';

If you have the C++20 Range library, you don’t have to write something like this yourself but can use a split_view.


Big hat tip to Dr. Bjarne Stroustrup for taking on this interview and giving us ample feedback during the design phase of our Learn C++ course.

It’s been an absolute pleasure and honor working with you, and thank you once again for everything you’ve done for the software and hardware communities.

For more information on C++20: https://isocpp.org.

Get more practice, more projects, and more guidance.