Slashdot Mirror


Stroustrup Says C++ Education Needs To Improve

simoniker writes "Over at Dr. Dobb's, C++ creator Bjarne Stroustrup has given an in-depth interview dealing with, among other things, the upcoming C++0x programming standard, as well as his views on the past and future of C++. He comments in particular on some of the difficulties in educating people on C++: 'In the early days of C++, I worried a lot about "not being able to teach teachers fast enough." I had reason to worry because much of the obvious poor use of C++ can be traced to fundamental misunderstandings among educators. I obviously failed to articulate my ideals and principles sufficiently.' Stroustrup also notes, 'Given that the problems are not restricted to C++, I'm not alone in that. As far as I can see, every large programming community suffers, so the problem is one of scale.' We've discussed Stroustrup's views on C++ in the past."

6 of 567 comments (clear)

  1. more to it by g2devi · · Score: 5, Interesting

    That may be so, but there's more to it. It's only been recently fully implemented and a few years ago Stroustrup himself commented that he's constantly surprised that some things (e.g. template recursion) are even possible in C++.

    The language is overly complex. The key advice any C++ expert is "restrict yourself to a specific subset of C++". That's the bulk of the difficulty. If C++ were simplified to include only that subset, you'd have a lot less need for training,

    1. Re:more to it by shutdown+-p+now · · Score: 5, Interesting
      Unfortunately, even if you keep away from the more advanced stuff such as template metaprogramming, there's still plenty of surprising (in a bad sense) behavior in the most basic C++ constructs (mostly inherited from C, but exacerbated by C++ pretense at high-levelness, and with some new stuff thrown in for good measure). Pointer arithmetic, unsigned types, silent implicit narrowing conversions, PODs vs non-PODs (which in turn separate into aggregate types and everything else) and the subtle differences in initialization of those, ability to delete void* and pointers to incomplete types (and the wonders of virtual destructors), etc... The language is a mess, really. It is very powerful, and the existing code generators are very good at optimizing stuff, but writing in C++, or any subset thereof, requires a very good understanding of subtle details.

      A simple example: given a vector of ints, calculate the average value, using standard idiomatic C++. Let's give it a try:

      #include <algorithm>
      #include <iomanip>
      #include <iostream>
      #include <istream>
      #include <iterator>
      #include <numeric>
      #include <ostream>
      #include <vector>

      int main()
      {
      std::vector<int> v;
      std::copy(std::istream_iterator<int>(std::cin), std::istream_iterator<int>(), std::back_inserter(v));
      int avg = std::accumulate(v.begin(), v.end(), 0) / v.size();
      std::cout << avg << std::endl;
      }
      A simple task, and a clean implementation, using the standard library as much as possible. No fancy language features used - no template metaprogramming, no pointers, no virtual inheritance. The kind of stuff a new C++ programmer might write after reading Stroustrop. And yet, it gives wrong result for certain input data. Now, who'll be the first one to spot and explain the problem here, preferrably without actually running it? Bonus points for explaining why we need "istream", "ostream" and "iomanip" headers here in addition to "iostream" (and we do, if we want this to be portable).
    2. Re:more to it by truedfx · · Score: 5, Interesting

      I'll admit I had to run the program, and even then it took me a while to see it.

      v.size() has vector<int>::size_type as its return type. Depending on which specific type, either that type will be converted to int, and all is fine, or the result of std::accumulate(v.begin(), v.end(), 0) is converted to an unsigned type, then divided, and then converted back to int. In the latter case, when you have a negative sum, the division gives the wrong result.

      I think the <istream> and <ostream> headers are required because the types of std::cin and std::cout might otherwise be incomplete, meaning operator<< might be undeclared. I know the <ostream> header is also required to that std::endl is declared. I'm not seeing what could be in <iomanip> that's of interest of your program. Could you explain that last one?

  2. Re:Education, even at Universities, needs to Impro by IamTheRealMike · · Score: 5, Interesting

    My university course spent about half an hour on pointers in a 3 year course. Most of that half hour was factually wrong: the slides were full of code samples that wouldn't compile or would always crash.

    They did, however, spend two terms teaching Hoare logic. Or rather, they spent one term teaching it, and then repeated the same material in another term with a different lecturer, because their communication was so poor they never realised they had duplicated their teching.

    Friends at other universities reported similar stupidities, though not always on the same scale.

    C++ is a rather complex language, but simplifying it won't help. The problem is that low quality education is rampant.

  3. Strostrup is the problem by Animats · · Score: 5, Interesting

    The big problem with C++ is Strostrup. He's in denial about the fact that the language is fundamentally broken. But he's still influential in C++ circles. Thus, no one else can fix the mess at the bottom.

    The fundamental problem with C++ is that it has hiding ("abstraction") without memory safety. This is the cause of most of the world's buffer overflows. No other major language has that problem. C has neither hiding nor memory safety, so it is still vulnerable to buffer overflows, but they're to some extent visible at the place they occur. Pascal, Modula, Ada, Java, C#, and all the interpreted "scripting languages" have memory safety. C++ stands alone as a language where you can't see what's going on, and the compiler doesn't have enough information to check subscripts.

    The reaction of the C++ standards committee has been to try to paper over the problems at the bottom with a template layer. That didn't work. The template classes just hide the mess underneath; they don't make the language memory safe. There are too many places that raw pointers leak out and break any protection provided by the templates. The template language itself is deeply flawed, and attempts to fix it have resulted in a collection of "l33t features" understood and used by few, and too dangerous to use in production code.

    The fundamental cause of the trouble comes from C's "pointer=array" equivalence. That was a terrible mistake, borrowed from BCPL. The trouble is that the compiler knows neither which variables are arrays nor how big the arrays are. You can't even talk about arrays properly. I mean, of course,
    int read(int fd, char* buf, size_t len);
    That's just trouble waiting to happen. "read" has no information about how big "buf" is.

    C++ added references to C, and should have added syntax like
    int read(int fd, char& buf[len], size_t len);
    to go along with it, so that arrays became first-class objects with sizes. But it didn't. There are some other things that have to be done to the language to make this concept work, but this is the general idea. This is the elephant in the living room of C++, and Strostrup is in denial about it.

    Every time you have another crash from a buffer overflow, every time you install another patch to fix a buffer overflow, every time you have a security break-in from a buffer overflow, think of this.

  4. Re:C++ has issues by SageMusings · · Score: 5, Interesting

    Real Mike,
    you have my full attention. Please, support your assertion that Java and C# suck rocks.

    C++ can be fast at execution time but the development time is prohibitive in many applications where you need to be agile and actually ship code in a hurry. I try not to get hung up on all the esoteric points of different programming languages, although I am quite amused to read other's comments. Yet, I will hazard a post on this topic.

    I learned C++, not all of it to be sure, but the portions 85% of us might need in a given project. It may be intellectually stimulating to code an app form a "purest perspective" but many of us have to earn a living and produce a lot of code in short order. C++ does not fit this bill. Most applications just have to work and work today, not next quarter. Then we have to extend the app after a few months. Since C++ is quite a bit harder to read and I have to learn code I did not write in short order to perform this maintenance, I enjoy Java and C# apps a lot more than ones coded in C++.

    Please, tell me why Java and C# suck compared to C++ in the practical world. Nearly all of us are not writing low-level, time-critical code. Most of us write apps for business transactions. I happen to write business software that is widely distributed and the C++ performance boost is nullified by the latency of remote calls to distant servers.

    Please, tell me the advantage of writing an app in a year vice 6 months.

    There are many languages because there are many problem domains. C++ is not the best language. There is no best language, period.

    Nearly all serious desktop software

    Finally, it has been my observation most "serious" code is no longer constrained to the desktop.

    --
    -- Posted from my parent's basement