Cee Plus Plus Not Slower Than Cee

[Supposedly as compared with CeePlusPlusSlowerThanCee]

Mainly from those who "love" CeePlusPlus there is an argument made the C++ programs aren't really slower (or larger) than functionally equivalent CeeLanguage programs.

Your questions above don't seem to quite fit the intent of this page title.
Well, one of the obvious issues is the vtable. Virtual functions force presence of a vtable, which expands every such object, sometimes dramatically, and also somewhat slows down otherwise lightweight method calls, since an indirection must be done.

It depends on the program, but there are cases where that all by itself can add up to a dramatic increase in time and space both.

A counterargument might be that methods should always be so heavyweight that the overhead of the vtable indirection is negligible. There are many such programs, but it is questionable that this is the best OO style.

Another counterargument potentially is that virtual functions should be rare enough that this time/space overhead shouldn't dominate.

The pointer-to-vtable typically expands each object by exactly one pointer. This isn't much. Also note, that you would need the equivalent of the pointer in C as well if you want to manually implement DynamicDispatch using PointerCastPolymorphism, if not, you wouldn't need virtual methods in the first place. [I would disagree with the vtable argument. I always felt that giving up jump tables when I went from assembly to C was a step backwards. C++ restored them with vtables. Jump tables/vtables were always more efficient in terms of code size and execution time over repeated if/else if or switch statements.]

Both of those comments are, unfortunately, incorrect, and misunderstand C++: Huh? That sounds like an incredibly stupid C++ compiler. The speed cost of a pointer to the vtable is an extra indirection: it's (*(object->_vtable[function_index]))(args) instead of (*(object[function_index + vtable_index]))(args). The space cost is (data members + function members) / (data members + 1). Both of these costs are known at compile time: the compiler has to know how many data members there are in order to lay out the object, and how many function members in order to build the vtable. So why can't it, based on whatever speed/space tradeoffs it uses for inlining, decide whether a pointer to a shared vtable or an inline vtable is more appropriate? -- JonathanTang

In fact, VeeTables were one of the things I had in mind when I created this page. Usually I tell my students that the alternative to a VeeTable is a an additional flag as discriminator within the object (or struct, if we move from C to C++).

This would more or less outweigh the overhead on the data side (per object VeeTable-Pointer). Furthermore, it saves a number of decisions implemented on the client side (which is typically a bad thing considering maintenance costs). Opinions seem to differ here, so does anybody have HARD NUMBERS on this, e.g. from refactoring an application from one style to the other and comparing costs = size, speed, later maintenance effort? Well, hard numbers on the latter will probably not impossible, as you had to continue the original AND the refactored program and applied the same changes to both, But maybe someone has done this with his/her students, e.g. splitting a class (students I mean here :-)) and let only one half work OO style.

"Jump tables/vtables were always more efficient in terms of code size and execution time over repeated if/else if or switch statements."

Have a look at the implementation of SmallEiffel, I think it specifically contradicts this statement. The whole-program optimizer for SmallEiffel translates dynamic dispatches to a set of known candidate methods into an if-then-else structure that chooses the correct method and calls it statically. They found that on modern hardware (deep pipelines, heavy reliance on branch prediction, etc) this was actually faster than using vtables.

One area where C++ programs tend to be slower than C is that C++ programs tend to have more methods of smaller size. This leads to more subroutine calls and returns, which take more execution time (I don't think it is a significant difference, but it is there). Although this is more of a code structure issue than a language issue, C++ seems to reinforce the object approach while C reinforces the procedural approach.

The flip side of this is that those tiny C++ methods are often (usually) inlined. The C++ code is just as fast; it's just written in a style which is easier to read and modify. But here's the catch: C derives its performance from being simple, while C++ relies on good compiler optimizations to generate fast code. The result is that a good optimizing C++ compiler will produce code that is just as fast as C in most situations (even though the programmer is using the more powerful features of C++). However, bad code can easily be slower than C and--here's the rub--*unless your C++ compiler is really good* you might not get a fast binary.
Anything that can be written in C can be written at least as well in C++. If the problem calls for tight, quick code, you use C++ the same way you would C. If the problem calls for powerful abstractions and reusability, you use more advanced features of C++. Most applications call for a mixture of the two: small, fast code at the low level and inner loops; broad abstractions for higher-level code.

I say C++ is at least as good as C, because C++ is more expressive. Therefore, it can do what C can do, plus a lot more. Even as just "a better C," C++ is indeed a better C. Features like inline functions and templates outdo #defines, because they allow the compiler to use its specialized knowledge in order to generate better assembly code. Even simple classes I have used to generate easily readable, easily maintainable, low-level code that's at least as fast as the equivalent C code. (I know it is because I looked at the generated assembly!) But in all cases, the C++ code was easier to read and easier to maintain.

For higher functions, C++ provides higher-level features. The key is to choose wisely based on the cost and benefit of each feature.

(This should all be obvious. The C++ code would not be slower or more obfuscated if I were trying to write clear, fast code. Since C++ is more expressive, C++ gave me more tools I could use to achieve that goal, and I used the language in pursuit of that goal. Therefore, C++ gave me at least what I could get out of C, plus even more. If a C++ feature would lead me further from my goal, I chose not to use that feature. The worst I could possibly do would be to end up with C++ as a better C. Therefore, C++ is at least as good as C in meeting my goals.)

Since C++ is more expressive than C, there is no good reason to choose C over C++. Objections to C++ in my experience have come (a) from programmers who spent years learning C but haven't taken the same time to learn the distinctives of C++ or (b) from those who repeat unverified rumors. Unfortunately, much C++ code has been generated by the former, lending credence to the latter.

Actually, I can think of two reasons you might choose C over C++ (though they only apply in some rare situations): (1) you need the widest possible portability, or (2) you need to target platform(s) for which no decent C++ compiler exists. This might happen to you in the embedded space, for example. Widespread porting of GnuCee and GnuCpp has made this less of an issue than it used to be.

I can think of a few good reasons to choose C over C++: Granted, none of these have anything to do with performance, and hence are a bit off-topic for this page. And I do think most objections to C++ (as opposed to C, not as opposed to CommonLisp ;) come from people who don't know what they're talking about. But there're several real-world projects (eg. ParrotCode and GTK) that are much easier to work with because they're in C instead of C++.

See also http://www.objectmentor.com/resources/articles/WhyAreYouStillUsingC.pdf

EditHint: Does this last section belong on a different page? Which one?

CategoryCee; CategoryCpp

View edit of March 2, 2006 or FindPage with title or text search