Often an argument is made that C++ is inherently and unavoidably '''slower''' than C. What is your experience? ** As Gunnar says below, "C++ was designed to be AsFastAsCee if you didn't use any C++ features". A lot of the arguments below seem to interpret the question differently: "unavoidably slower if you don't use C++ features", versus "unavoidably slower if you do use C++ features (e.g. in a way natural for C++)". A certain percentage of the arguments could probably be brought into agreement simply by clarifying which of those two questions is being discussed. * Is there really some "silent" overhead without any benefit? (In my experience such unavoidable overhead mainly stems from exception handling '''if''' you neither use nor need it. But for this purpose there are compiler options to disable exceptions completely, if a program doesn't use them.) * Or do we compare apples with apple pie? (There is more effort in preparing apple pie compared to buying raw apples, so if you compare the "price" of apples to the price of apple pie you might ask why is apple pie so expensive compared to it's ingredients? Considering C++ vs. C; Might it be that some simply forget that in an equivalent C program they had to add manually many things the C++ compiler inserts automatically. So, in the last and final, a C and C++ program with comparable functionality are about the same speed or size?) * Or is it because some use C++ without being aware of "hidden costs". (E.g. there seems a widespread misconception that destructors have something to do with freeing memory. So, in fear of memory could leak otherwise, I've sometimes observed that EMPTY - and non-inline(!) - destructors were added to each and every class, of course slowing down a C++ program MUCH.) ----- In a narrow, technical, sense, it's obvious that C++ is not ''necessarily'' slower than C; while C is not a true subset of C++, it's close enough so that one could write standard C++ that was pretty much indistinguishable from the equivalent C program. The issue is whether using constructs only found in C++ necessarily makes programs slower. This is best addressed by looking at the cost/benefit of particular C++ constructs. * If someone (mis)uses templates or inheritance where not needed, they'll get the downside with no upside. So that's one potential problem. * If someone doesn't understand OO programming, and/or they use it in a situation where it is not a great fit (such as matrix mathematics), that also will be a potential problem. * If someone is using a compiler that doesn't handle some section of the language very well (templates, exceptions, etc), that also is a potential problem. * If someone writes something that is just flat-out bad, because they optimize too early and the structure is unclear, or because they accrete the program as a series of ill-thought-out patches, then that also is a potential problem. And so on. But one can write ''blazingly fast'' programs in C++, as long as one's aware of the potential pitfalls. And, yes, you can use exception handling too, along with everything else. ---- As far as I know (from TheCeePlusPlusProgrammingLanguage IIRCs) C++ was designed to be AsFastAsCee if you didn't use any C++ features. Particularly the ExceptionHandling did bother implementors quite a bit, because 'simply' adding a heap record for try-catch blocks wouldn't do under such a requirement. -- .gz ---- Discussion on inlining moved to CeePlusPlusInlining. '''...and the following moved back, since it has nothing to do with inlining: ''From CeeLanguage:'' CeePlusPlus was one effort to add ObjectOriented capabilities, and it adds an extra expense to every single method (function) call made, even in pretty trivial cases. ''Calls to static class methods, non-virtual class methods, and free functions (functions not part of a class, just like in plain old C) have exactly the same semantics as a C function call. If a function is implemented in C++, there may be additional stuff in the function prologue/epilogue to deal with exception handling; functions implemented in C don't incur this expense. If no exceptions are thrown, we're talking a few instructions. Calls to virtual functions incur an additional expense, as a) you need to look up the actual function to call (and adjust the this pointer) for such calls; and b) virtual functions prevent inlining in many cases--unless the compiler can prove which version of a function will be called. The overhead of a) above is generally a few instructions.'' In complex cases it can cause a function call to consume thousands of machine instructions before it even gets to the function's body. ''Under what conditions? Even with multiple inheritance and exceptions--the number of instructions needed to resolve any C++ function call is bounded--and several orders of magnitude lower than "thousands". Now, if a function call causes a page fault and you count the instructions that the OS uses to service the page fault, that's another matter--but that affects C just as much as C++.'' '''It is infamous that people are often astonished to single step through their code, and quite literally discover that thousands of machine instructions occur before they reach the method body they thought they were calling directly. If you think about it for a second, you'll recall that this does happen.''' [But we don't remember that. I spent several years stepping through C++ code at the instruction level on VMS and I never saw it take thousands of instructions. Perhaps there's some particularly bad C++ implementation out there, but I haven't seen it.] ''I'm talking about the experience where people are astonished at the vast numbers of constructors, often including many many trivial constructors, but also including nontrivial ones that call nontrivial code, that get called that they didn't realize would get called. This used to be even worse than it is today, but it happens even with good C++ implementations, because the language is just doing what it was told to do, but regardless, it happens. In C, there are no such hidden costs. A call is just a call in C.'' {Right. But that's a vastly different thing than the statement that was being critiqued above, which is completely wrong. Dynamically-dispatched virtual function calls add a small amount of overhead. If you use the OO features sparingly, that's all the cost you pay -- and it's usually offset by the savings in conditionals. Unwise use of some features -- e.g. passing complex objects by value, which would cause the constructor overhead you mention -- can lead to a lot of overhead. But the answer to that is "don't do it". If people are astonished by such things, it's because they didn't learn their tools well enough. If such features are used ''appropriately'', they add overhead which offsets the savings you get from not writing a lot of code that does similar, necessary things -- like allocating and copying data. -- DanMuller} It is not vastly different, and the original was not completely wrong, and you are not disagreeing, you're in violent agreement. :-) You said "small amount of overhead...sparingly, that's all the cost you pay." The original said "adds an extra expense...In complex cases it can cause a function call to consume thousands of machine instructions ". Those two statements are in agreement. At most the argument is about emphasis, like in the old joke, "we've already established what you are, now we're just haggling over price." ;-) -- DougMerritt Er, OK, I might have slightly overstated the case. I retract "vastly". But your selection of quotations skip over the true error: ".. it adds an extra expense to '''every single''' method (function) call made.." [emphasis mine] ''is'' actually wrong. Typical C++ -- notice I'm not saying 'well-written' C++ -- has a lot more non-virtual member functions than virtual ones. And those don't pay ''any'' inherent extra expense -- non, nada, zippo. ''If'' you pass complex objects by value, you'll add overhead -- but again, in my experience, this is not a terribly common to mistake among minimally educated C++ developers. So -- yes, completely wrong because it was stated as an absolute, and even if you replace "every single" with "most", still wrong, according to my experience. The discussion also ignores the fact that at ''least'' some of that overhead is replacing things that you would have had to write out explicitly if C++ didn't allow for a greater economy of expression. (I can't believe I just wrote that -- C++ is still way too verbose.) Yeah, it's true that a lot happens implicitly which would be explicit in C, so if you're not familiar with the characteristics of data structures that you're using, you can get surprised. But with ''reasonable'' care and only a few good coding guidelines, this can be, and in my experience usually is, avoided. -- DanMuller Good style is virtual, which has overhead, typical style is non-virtual, but that still invokes constructors, which is overhead. You can assume constructors are optimized into inline code, but are they always? No. Are they by default? No. Does C++ style (good or bad) cause very frequent use of constructors, e.g. for member initialization? Of course. Even if optimized into inline assignments rather than function calls, is there a resulting increase in the amount of code compared with C? Yes. In "complex cases", as above, can this amount to thousands of machine instructions before the method's main body is reached? Absolutely; I've seen it happen. I've worked on the internals of multiple C++ compilers professionally, in addition to using C++ in various non-compiler projects. I've seen a huge amount of different kinds of code. I'm not making this up. But notice, I'm not making any blanket statements like "...and therefore C++ is always slower than C", which would be easy to think I am implying, but I'm not claiming that. I'm merely claiming that in C, a call is just a call, but that more often than not, that's not the case in C++. This may or may not matter in individual instances. BTW someone above claimed that "inline" would always inline. I'm a few years out of date, but that used to be absolutely false, it was advisory only, and compilers would typically refuse to inline functions larger than some threshold in size, nor was there any standard way to force the issue, nor to get a warning if the compiler did not inline. Did this change in a newer version of the ever-changing C++ standard? -- DougMerritt I disagree only with this: "Good style is virtual." Where I've worked, it's: "Good style is using the language features you need." * Well, I was speaking sloppily. Good style is complicated. It also is not always the same thing as "best practice", which takes vastly more things into account than just style. Considering style alone, virtual tends to be underused in C++. ------- There is another case where the C++ form is slower (or takes more data space...) than the C form: pointer to function Vs. pointer to member function. ''Apples to oranges. C-style FunctionPointer''''''s exist in C++, and take the same amount of space. PointerToMember''''''s are an altogether different beast; you use them in a different context. In many years of C++ programming, I seldom find a need to use PointerToMember''''''s.'' * How frequently a construct is needed (A) varies per application domain and per programmer, and (B) more importantly, is unrelated to whether it is slower or not when it '''is''' used. Obviously, pointer to member function is slower than pointer to function, but to reinterpret your point, it won't tend to measurably impact the overall speed of a program in most instances. But if one is shaving cycles in an inner loop, that would be something to look at. ---- I rarely work at or near the UI level; much of the software I've worked on is supporting middle-layer code and lower. In such code, where performance often can become an issue, I've always had this habit. The result is that virtual functions are easily the exception rather than the rule. Also, I and those I've worked with make heavy use of const reference parameters. If I suspect that an object is larger than a pointer, then I would not usually pass it by value unless there was an advantage to having a mutable copy on the stack at the receiving end. This means that such objects are almost always being passed in exactly the same way that you'd pass a struct in a C program. Given these habits, I don't expect most function calls to incur more overhead than a C call. Am I missing something? * Yes, you're talking about passing objects to methods. I was talking about the transparent automatic invocation of constructors in particular. The overhead of such is not necessarily an issue, but it exists. To answer the question at the top of page carefully and completely ("Often an argument is made that C++ is '''inherently''' and '''unavoidably''' '''slower''' than C. What is your experience?"), I've never done a strict performance comparison between similar programs written in C versus C++. However, I've spent quite a bit of time investigating performance deficiencies in C++ code. Rarely, if ever, was a problem due to overhead inherent to using C++. That's not to say that there wasn't such overhead, but it doesn't make it onto the radar screen as an issue. * I'd mostly agree, but part of the point is that making best stylistic use of C++ can impact performance -- and yet again: that often doesn't matter. This is a different question than whether it is possible to code for high performance in C++. It is possible. And it's not always in conflict with best style. But sometimes it is. Occasionally I work on code with very compute- or data-intensive algorithms. In such cases, where I know (or find out very quickly) that performance is an issue, I will sometimes end up writing in a style that's much closer to plain C. In such cases, you do have to stay aware of what the various C++ features actually do (or can do). But I'm having trouble thinking of any performance overhead in C++ that is ''unavoidable''. Perhaps common standard library routines suffer from some inherent overhead due to support for language features that you might or might not use? (Cf. the following poster's comment on exceptions.) I don't know. -- DanMuller * Well, actually, that is often the case ("string" has been criticized to death, for instance), but not what I'm talking about. ''For an apples-to-apples comparison of C and C++, the best test is to compile C code with the C++ compiler (assuming, of course, the C code is valid C++; C code that isn't valid C++ usually contains a C++ keyword as an identifier, such as "int class;", or else contains some sloppy construct that C tolerates but C++ doesn't). If you see '''any''' significant performance difference, you should upgrade your compiler/toolchain. (Also consider repeating the experiment with exceptions disabled, if the compiler allows that).'' (Agreed! -- DanM) Agreed. And actually, exceptions can in fact make a difference. It sometimes makes a performance difference to make sure that the compiler knows where exceptions are not thrown. The compiler's life is a hard one; pity it. -- Doug ---- CategoryCee CategoryCpp