Your counterargument boils down to "use C instead". That is exactly what I am currently advocating.
I don't blame C++ for screwing up - I blame it for being an ill-designed language that makes it easy to screw up.
Any of the high-level features of C++ are well-implemented in any number of decent languages that don't obfuscate your code and incur horrible link times. And my argument (for game development) is that C++ is indeed the wrong language for the domain. In fact, I'd argue it's wrong for most, if not all domains. And I'm not exactly alone - I can't recall any prominent figure that actually thinks C++ is a decent language, except Bjarne Stroustrup. (Correct me if I'm wrong - I'd love to hear about it!)
<blockquote>
If you want them attributed to the callee, it's pretty simple. Do the coercions in the callee, just like you would have in C.
</blockquote>
The issue is that in many instances, I own the caller, but not the callee. And the person owning the callee can unintentionally make my code perform worse by simply changing the API. Or adding a destructor.
No, my counterargument is to use the features of C++ when they help and not when they hurt. I claim that C++ doesn't hurt C programmers. It just brings out their deficiencies in different ways. For instance, embracing features you don't understand and then complaining about the consequences is stupid, and stupid people don't write good code in any language. You understand C++ well enough to know the pros and cons (or at least the cons) of various C++ language features, but you complain that your fellow programmers might not:
The issue is that in many instances, I own the caller, but not the callee. And the person owning the callee can unintentionally make my code perform worse by simply changing the API. Or adding a destructor.
This is just bad programming practice on their part. The performance cost of a destructor shouldn't be a surprise to the person who writes it. If someone is messing with the performance of types you use or removing functions(+) you call without consulting you and without themselves taking responsibility for calls to that functionality, then obscure features of C++ is just one of the many ways they're going to screw you on a regular basis. How would those programmers screw you in C? I don't know, but I know they would.
Nobody who knows C++ well enough to use it effectively would call it a "decent" language in the sense of "not obscene," but it is definitely "decent" in the sense of "adequate." It's easiest to define C++'s deficiencies with respect to other languages (for instance, memory management in C++ is much more intrusive in source code than in Java) but comparing it to C is way too simple. After all, the primary problem with C++ is that it doesn't remove any of C's dangers; it just gives you better ways of abstracting them away in some cases. The second problem with C++ is that it's extremely complicated and takes a long time to learn. And that's it. Every other supposed misfeature of C++ (relative to C) seems to stem from people hitting the second problem without realizing it. In your case, your coworkers should be more conservative about messing with things (such as defining expensive automatic type conversion functions) when they don't understand the consequences (such as those type conversions actually being invoked.)
(+) This is the most plausible explanation for different type conversions suddenly being invoked. It could also happen by adding a function that invokes a more expensive type conversion to a type that is more closely related to the type declared by the caller, thus making the new function a better match than the old one, but it's unlikely that a conversion between two types that are more closely related would actually be more expensive.
No, my counterargument is to use the features of C++ when they help and not when they hurt.
That was Stroustrups reasoning: "Only pay the cost when you use it". In retrospect, believe that that's a bad choice for language design, because there's a good chance somebody will use a feature without fully understanding the ramifications it has over the entire code base.
C opts for the opposite and uses annotation to treat certain code segments as "special" and make them faster - "inline", and (in the distant past) "register" come to mind.
(or at least the cons)
I believe I do get the pros as well, at least to some extent. I've been using it since CFront came out ;) And I'd still advocate it for use in a small team (<5 people?) of experienced programmers - you can make it sing.
But gamedev engineering teams are at least 15+ people, with the occasionally less-experienced ones thrown into the mix. C++ is, in a sense, like a professional power tool. It sure can get stuff done, but the wrong person uses it and its a blood bath, and it's not appropriate for single small home repairs. (Gah. Bad analogy, but I can't come up with a better one right now)
This is just bad programming practice on their part. The performance cost of a destructor shouldn't be a surprise to the person who writes it
Possibly. I'd argue that it's hard to always keep all performance ramifications in mind. But let's for a moment say it's indeed simply bad programming practice - the issue that makes this a problem is that my code pays the cost, not the offending code. Which is a rather indirect.
C++ changes often have tendrils all through the system. It is easy to make inadvertent mistakes.
* but it is definitely "decent" in the sense of "adequate.*
It clearly gets the job done, yes. We are shipping games occasionally, after all. I'm looking for better ways to ship games, and I think that abandoning C++ might bring gains.
The second problem with C++ is that it's extremely complicated and takes a long time to learn.
That's what my hidden cost is referring to - C++'s complexity makes it hard to understand. You certainly can write code that performs well in C++, but it is arguably harder to get it right than C.
I like to think there's a better solution than either one hiding somewhere, but I haven't found it yet.
And you can make your code slower by changing it! Oh the horror. C++ is, imo, a good language for a lot of domains. What goes wrong is when people try to use all of the features that C++ offers instead of just using the ones applicable to their domain, eg. I don't think you would really want to use exceptions in embedded programming. If you are on a platform where performance is the key, then you should be careful of what you are doing.
I think people are mostly blaming C++ instead of bad programmers.
The point is not that I can make the code slower by changing it. The point is that it can get slower by changes to the API, without any changes to functionality.Made by somebody else, unintentionally impacting me.
Let me ask you this: Have you ever worked on a large scale C++ project that didn't have performance issues? Or memory issues?
The difference is that the API can change without visible API changes. If you add a virtual destructor to your class, I won't notice that by looking at the call site. I've just been burdened with additional overhead, without knowing about it.
And yes, large projects have large project issues. It is kind of telling that C++ needs an entire tome on large project issues, though... (Lakos, Large Scale C++ Software Design)
The difference is that the API can change without visible API changes.
I don't understand this at all. The performance of a C function can change without any change to the function signature. Even the destructor scenario can happen invisibly in C code for any type that already has a cleanup function. No matter whether the cleanup function is defined as "int myproj_FooCleanup(struct Foo* foo) {...}" or "myproj::Foo::~Foo() {...}", you won't notice implementation changes until runtime.
I'm not talking about the performance of the function itself, I'm talking about the overhead incurred. That can't change in C.
Also, just adding a virtual destructor (without any functionality) adds cost. And unfortunately, you need to if your class happens to become a base class.
I don't blame C++ for screwing up - I blame it for being an ill-designed language that makes it easy to screw up.
Any of the high-level features of C++ are well-implemented in any number of decent languages that don't obfuscate your code and incur horrible link times. And my argument (for game development) is that C++ is indeed the wrong language for the domain. In fact, I'd argue it's wrong for most, if not all domains. And I'm not exactly alone - I can't recall any prominent figure that actually thinks C++ is a decent language, except Bjarne Stroustrup. (Correct me if I'm wrong - I'd love to hear about it!)
<blockquote> If you want them attributed to the callee, it's pretty simple. Do the coercions in the callee, just like you would have in C. </blockquote>
The issue is that in many instances, I own the caller, but not the callee. And the person owning the callee can unintentionally make my code perform worse by simply changing the API. Or adding a destructor.