> > C++ is an exteremely 'complicated' if you need efficiency. Whereas
> > C has a reasonably constant number of assemby instructions per
> > C instruction (I think it averages around 5), C++ has a greatly
> > varying number of assembler statements per C++ statement, it may
> > be more than 500! (If you consider for instance an 'elegant'
> > construction

With optimizing compilers - this is a non-issue, and just like a C programmer 
knows a division operation is much more expensive than an addition, a C++ 
programmer knows a temporary construction and "implicit" copy constructions 
are more expensive than other alternatives.
I doubt the highest optimization level in a typical C compiler will generate 
a "reasonably constant number of assembly instructions per C instruction", 
and on CISCs such as Intel, this number would be meaningless anyhow.
Some operations are expensive, this should be known to the programmer, in 
both C and C++, when calling expensive functions, or in C++: when invoking 
expensive language operations.  Almost all interesting work in C is done via 
function-calling anyhow, so you shouldn't compare the primitives of the one 
language with the other, but rather the whole thing.  To a C++ programmer, 
the explicitness of the cost of copy-construction is as explicit as the cost 
of calling any expensive function.

C++ has very little implicitness added to C, most of it is actually pretty 
good:
A) Object copy construction when passing as parameter or a return value (hard 
to say it is very implicit though, because one explicitly chooses to pass by 
value, and thus copy-construct).
B) Automatic destruction: This is probably a good thing, at least if 
destruction is used properly - for cleanup of resources.  And sometimes for 
the nice 'scoping trick' (of using a construction/destruction to act upon an 
entrance/exiting of a scope, for a lot of easy debugging information, very 
safe scope-bounded locks, etc.)
C) Indirection level of function call:  Virtual functions calling syntax is 
the same, although it may be one indirection/pointer-level more expensive. 
This is a Good Thing (TM) as the addition is not very expensive, and quite 
explicit on the defining side (except for the lack of need to re-specify it 
in deriving methods).
D) Unexpected flow of code when not specifying the throw():  Probably a very 
good thing, that allows 100% error handling, that never forgets to handle an 
error, and easily classifies errors and encompasses their treatment code in 
the right places.  If you want, you can always specify exactly what you throw 
and make the flow of code quite explicit.
E) member-scoping: (no need to specify this->) Yes, I agree this is a 
seriously problematic feature, which is definitely evil, and I myself had 
encountered quite a few bugs over it (Accessing the wrong variable).

> I agree completely with all of this.  I also hate the implicit
> member usage scoping.  If you want to use a field or member function,
> you should have to explicitly use the entire hierachy right from
> the this-> pointer. 
I agree

> The words 'implicit', 'elegant', 'suggested',
> and other ambiguities do NOT belong in a spec for a real-world
> product.  All you end up with are bug potentials, opacity, obscurity,
> incompatibilities, etc.
With most implicit things, such as implicit side-effects, and 'suggested' 
things that are used to affect what really happens, you're probably right.  
When it comes to abstracting more from the programmer (such as virtual 
function calls, or allowing temporarily construction of objects to 
type-safely send information between functions, or handling errors separately 
allowing return codes to be used properly) is bug-eliminating, and reduces 
the complexity of the code, allowing the programmer to deal with real bugs.
Also consider automatic memory management, which is known to reduce the 
number of bugs significantly, even though it adds implicitness and 
abstraction.

> Use of C++ code as a callback from C - yep there's lots of C out there,
> implementation of the this-> pointer, #ifdef nastiness to get rid of the
> this pointer, implementation dependence of the this pointer passing between
> compilers... just some more of my pet peaves about the langauge.
The lack of binary standards is surely a C++ problem.  ORB's, and COM seem to 
address this problem. Problem is, COM is Windows-specific and noone uses 
CORBA/etc.

> There are other dimensions of C++ that are just plain broken,
> due to fsck-ups in the spec.  I don't even want to revisit them
> in my mind.  Wish I had written them up into a doc first, but my urge
> to throw my notes into the garbarge was too great and too satisfying...
Yes, most of them are actually derived from C :)  Lack of array safety is a 
major one.  void*, the mere concept of casting (which should be represented 
as construction-of, and not as casting), and other type-hellish C things are 
other major problems. 
Most of the things that bother me are actually its lack of abstraction and 
OVER-explicitness, such as having the redundancy of having both indentation 
and {} markers, which after using Python for a while, feels really stupid 
(There are serious problems that can result from loss of synchronization 
between the two representations, and it allows misleading code).
Static typing has many merits, but from experience it is usually 
counter-productive, although makes optimizing easier (although in theory it 
should not be more optimized).
Virtual functions are not the default, also increasing some unwanted 
explicitness.
The annoying redundancy of declaration and definition of things that can 
known automatically.

Another note:
Soon optimization is a serious problem many C programmers have.  They 
optimize the code on a local-level, and put time and effort into it, when 
writing the code, rather than writing it quickly, reliably and safely, 
optimizing the algorithmic levels, and only when profiling information is 
available, optimize the local-level code.
Local-level optimizations lead to more confusing code, that tends to have 
more bugs and make more implicit assumptions.  And for what?  To save a few 
cycles once in a few seconds?  Only optimize where it matters.

Eyal

Reply via email to