Why We Use C Than C++...

U

Ulrich Eckhardt

Shark said:
I think what you say about automatic cleanup is true if the destructor
itself doesn't throw an exception!

A destructor must not throw an exception, that's a rule of C++. If, inside
a dtor, you need to perform an action that might throw, you need to take
precautions that the exception doesn't propagate outside the dtor.

Uli
 
U

Ulrich Eckhardt

Dag-Erling Smørgrav said:
in which case there is no point in chosing C++ over C.

Yes there is, you get C++ namespaces! Seriously, I wonder a) why nobody
has mentioned this point yet and b) why it's not part of C yet, I miss
them really much, and the prefix/suffix thing which is used in C is so
inelegant.

Uli
 
S

Shark

Ulrich said:
A destructor must not throw an exception, that's a rule of C++. If, inside
a dtor, you need to perform an action that might throw, you need to take
precautions that the exception doesn't propagate outside the dtor.

Well, I meant to say if an exception occurs when you are inside a
destructor and are trying to do some cleanup.......
 
I

Ico

Ulrich Eckhardt said:
Yes there is, you get C++ namespaces! Seriously, I wonder a) why nobody
has mentioned this point yet and b) why it's not part of C yet, I miss
them really much, and the prefix/suffix thing which is used in C is so
inelegant.

It's not my intention to start or take part in a holy war about C vs
C++, but I am seriously interested : what exactly do you mean with the
'prefix/suffix thing' ?
 
K

Keith Thompson

Ico said:
It's not my intention to start or take part in a holy war about C vs
C++, but I am seriously interested : what exactly do you mean with the
'prefix/suffix thing' ?

Global symbols in libraries have to be unique for a given program.
If two libraries use the same identifier, a program can't use both
libraries (unless you can modify one or the other or use some
implementation-specific ugliness).

The usual solution is to apply a unique prefix to all exported
identifiers. For example, an "xyz" library providing a "create"
function might call it "xyz_create()", avoiding a potential conflict
with "pdq_create()" from the "pdq" library.

This is a fairly ugly solution, and not all library authors follow it.

<OT>
C++'s namespace facility provides a cleaner way around this. For
example, an "xyz" library might put all its symbols in the "xyz"
namespace, giving symbol names like "xyz::create()". The difference
is that it's a feature built into the language, making it easier to
use and harder to avoid, and you can refer to the function as just
"create()" if you want to. (I don't use C++, so I could be missing
something.)
</OT>
 
I

Ico

Keith Thompson said:
Global symbols in libraries have to be unique for a given program.
If two libraries use the same identifier, a program can't use both
libraries (unless you can modify one or the other or use some
implementation-specific ugliness).

The usual solution is to apply a unique prefix to all exported
identifiers. For example, an "xyz" library providing a "create"
function might call it "xyz_create()", avoiding a potential conflict
with "pdq_create()" from the "pdq" library.

This is a fairly ugly solution, and not all library authors follow it.

Ah, I know the problem ( both as victim, and -I have to admit- as
perpetrator. Learning the hard way :) ), I was not aware he was
referring to this.
<OT>
C++'s namespace facility provides a cleaner way around this. For
example, an "xyz" library might put all its symbols in the "xyz"
namespace, giving symbol names like "xyz::create()". The difference
is that it's a feature built into the language, making it easier to
use and harder to avoid, and you can refer to the function as just
"create()" if you want to. (I don't use C++, so I could be missing
something.)
</OT>

Ok, that sounds as a useful feature.
 
I

Ian

Shark said:
Well, I meant to say if an exception occurs when you are inside a
destructor and are trying to do some cleanup.......
Then you have to handle it inside the destructor, just like any other
error condition, C or C++.

Ian
 
I

Ian

Ico said:
It's not my intention to start or take part in a holy war about C vs
C++, but I am seriously interested : what exactly do you mean with the
'prefix/suffix thing' ?

Function or variable names like someModeleDoSomething().

Ian
 
R

Richard Heathfield

Walter Bright said:
I'm not aware of any places where, compiling the same source code, it's
faster.

If you're using the same source code with identical semantics, it's true
that there's no particular reason for one to be faster than the other. But,
if you're using the same source code with identical semantics, why bother
with C++?
 
R

Richard Heathfield

Keith Thompson said:
[Prefixing] is a fairly ugly solution, and not all library
authors follow it.

<OT>
C++'s namespace facility provides a cleaner way around this. For
example, an "xyz" library might put all its symbols in the "xyz"
namespace, giving symbol names like "xyz::create()". The difference
is that it's a feature built into the language, making it easier to
use and harder to avoid, and you can refer to the function as just
"create()" if you want to. (I don't use C++, so I could be missing
something.)
</OT>

What you're missing is that it doesn't solve the problem, because Company A
and Company B can each wrap their libraries in the same namespace. This is
easily done, simply by not consulting each other when choosing a name for
the namespace. It probably doesn't happen much, but it probably does
happen!
 
L

Logan Shaw

Richard said:
Walter Bright said:
If you're using the same source code with identical semantics, it's true
that there's no particular reason for one to be faster than the other. But,
if you're using the same source code with identical semantics, why bother
with C++?

That's a good point. But, C++ has about 14 billion extra features
beyond that which C has. If restricting yourself to the C-like features
carries no performance penalty, doesn't it seem likely that at least a
few useful C++-only features have no performance penalty compared to
equivalent way of doing things in C?

For example, C++ allows you to do this:

int *i = new int[100];

There is no reason the performance of this should be any worse than
the C equivalent:

int *i = (int *) malloc (100 * sizeof (int));

But, which one is easier to write? Also, will the compiler catch
the error for you if you accidentally change the second one to this?

double *d = (double *) malloc (100 * sizeof (int));

Also templates carry no overhead compared to doing the equivalent
thing in C. In some cases, they can even make it easier to make
fast code. Say, for example, you need to implement sets of floats
and ints. With C, you write everything twice or you wastefully
store everything as void * values that point to the actual data.
C++ templates let you write the code only once and avoid the
performance penalties of dealing with pointers when you want to
deal directly with the native types. Of course, templates can
easily get out of control and lead to bloat, but they don't have
to if you use them wisely.

- Logan
 
M

Malcolm

Logan Shaw said:
For example, C++ allows you to do this:

int *i = new int[100];

There is no reason the performance of this should be any worse than
the C equivalent:

int *i = (int *) malloc (100 * sizeof (int));

But, which one is easier to write? Also, will the compiler catch
the error for you if you accidentally change the second one to this?

double *d = (double *) malloc (100 * sizeof (int));
Sure, but then you've got to remember whether to free() or delete your
array.
Also, you can overload the new operator to use a custom memory allocation
scheme. Care to tell me how to do this without looking it up?

Then you'll find that the consensus nowadays is that new is deprecated, you
should be using an stl vector instead.

These are the sorts of problems you get with a move to C++. A few benefits,
such as "new" being easier to type than "malloc()", are trivial in
comparison.
 
M

Michael Mair

Logan said:
Richard said:
Walter Bright said:
If you're using the same source code with identical semantics, it's
true that there's no particular reason for one to be faster than the
other. But, if you're using the same source code with identical
semantics, why bother with C++?

That's a good point. But, C++ has about 14 billion extra features
beyond that which C has. If restricting yourself to the C-like features
carries no performance penalty, doesn't it seem likely that at least a
few useful C++-only features have no performance penalty compared to
equivalent way of doing things in C?

For example, C++ allows you to do this:

int *i = new int[100];

There is no reason the performance of this should be any worse than
the C equivalent:

int *i = (int *) malloc (100 * sizeof (int));

But, which one is easier to write? Also, will the compiler catch
the error for you if you accidentally change the second one to this?

double *d = (double *) malloc (100 * sizeof (int));

*sigh*
That is why _C_ people write

T *p = malloc(size * sizeof *p);

Of course, you can do it the wrong way, as you demonstrated it,
but using the handle of the screwdriver to hammer down the screw
being peculiar at best does not convince me that using a screwdriver
with screws leads to nailed down screws.
Also templates carry no overhead compared to doing the equivalent
thing in C. In some cases, they can even make it easier to make
fast code. Say, for example, you need to implement sets of floats
and ints. With C, you write everything twice or you wastefully
store everything as void * values that point to the actual data.
C++ templates let you write the code only once and avoid the
performance penalties of dealing with pointers when you want to
deal directly with the native types. Of course, templates can
easily get out of control and lead to bloat, but they don't have
to if you use them wisely.

Agreed. Without a typeof operator or similar, C cannot match the
power of templates. Considering the number of template classes
and functions in a >1MLoC project I am involved in, the choice for
C++ certainly was not made because of templates but exactly in order
to have virtual functions, RTTI, etc such that design patterns can
be easily implemented.


Cheers
Michael
 
R

Richard Heathfield

Logan Shaw said:
That's a good point. But, C++ has about 14 billion extra features
beyond that which C has.

If you want those features, use C++.
If restricting yourself to the C-like features
carries no performance penalty, doesn't it seem likely that at least a
few useful C++-only features have no performance penalty compared to
equivalent way of doing things in C?

Put it this way: when I select C++ over C, my reasoning is not "this will be
no slower than C". Rather, it is "I am sufficiently desperate to use a C++
feature that it overcomes my innate preference for C".
For example, C++ allows you to do this:

int *i = new int[100];

There is no reason the performance of this should be any worse than
the C equivalent:

int *i = (int *) malloc (100 * sizeof (int));

But, which one is easier to write?

int *i = malloc(100 * sizeof *i);

(My fingers have it down pat now, and I can type it much faster than I can
type either of your choices.)

Also, will the compiler catch
the error for you if you accidentally change the second one to this?

double *d = (double *) malloc (100 * sizeof (int));

Let's see:

double *i = malloc(100 * sizeof *i);

Seems correct to me.

<snip>
 
W

Walter Bright

Richard Heathfield said:
Walter Bright said:


If you're using the same source code with identical semantics, it's true
that there's no particular reason for one to be faster than the other.
But, if you're using the same source code with identical semantics, why
bother
with C++?

It's perfectly reasonable to use C++ to pick and choose what features you
might want to use. It's clear that simply using a C++ compiler is not going
to slow your code down. There are many valid reasons why one might choose to
stick with C rather than C++, but performance isn't one of them.

There is one case where using a C++ compiler for C code may increase
performance - C++ uses a different function calling convention than C, a
faster one. The reason C compilers don't adopt it is for binary
compatibility with C compilers that predate function prototypes. The
difference (callee cleans the stack, rather than the caller) can amount to 1
to 3%. (Yes, I've measured it <g>.)

Walter Bright
www.digitalmars.com C, C++, D programming language compilers
 
?

=?ISO-8859-1?Q?Bj=F8rn_Augestad?=

Logan Shaw wrote:
[snip]
For example, C++ allows you to do this:

int *i = new int[100];

There is no reason the performance of this should be any worse than
the C equivalent:

int *i = (int *) malloc (100 * sizeof (int));

But, which one is easier to write?

Straw-mans argument, the proper way to do this in C is to write
int *i = malloc(100 * sizeof *i);

Now try to deallocate the memory in C++, how do you do that?
delete i;
or maybe
delete[] i;

Pretty inconsistent, isn't it, and also a common source to memory leaks,
IIRC.

Also, will the compiler catch
the error for you if you accidentally change the second one to this?

double *d = (double *) malloc (100 * sizeof (int));

Not an issue, see above.
Also templates carry no overhead compared to doing the equivalent
thing in C.

No size overhead either?
In some cases, they can even make it easier to make
fast code. Say, for example, you need to implement sets of floats
and ints. With C, you write everything twice or you wastefully
store everything as void * values that point to the actual data.
C++ templates let you write the code only once and avoid the
performance penalties of dealing with pointers when you want to
deal directly with the native types.

If *profiling* shows that this really is an issue, it can be solved.
Of course, templates can
easily get out of control and lead to bloat, but they don't have
to if you use them wisely.

Which is one of the major problems with C++, too many pitfalls.

Bjørn
 
K

Keith Thompson

Logan Shaw said:
For example, C++ allows you to do this:

int *i = new int[100];

There is no reason the performance of this should be any worse than
the C equivalent:

int *i = (int *) malloc (100 * sizeof (int));

But, which one is easier to write? Also, will the compiler catch
the error for you if you accidentally change the second one to this?

double *d = (double *) malloc (100 * sizeof (int));

No, which is why the recommended way of writing that is

double *d = malloc(100 * sizeof *d);
 
I

Ian

Malcolm said:
Sure, but then you've got to remember whether to free() or delete your
array.

That's one of the great benefits of C++, you don't if you use a smart
pointer. Smart pointer are a great way of removing memory leeks.
Also, you can overload the new operator to use a custom memory allocation
scheme. Care to tell me how to do this without looking it up?
void* operator new( size_t n ) throw( std::bad_alloc );
Then you'll find that the consensus nowadays is that new is deprecated, you
should be using an stl vector instead.
Is it? No one's told me... how do you think vector gets its memory?
These are the sorts of problems you get with a move to C++. A few benefits,
such as "new" being easier to type than "malloc()", are trivial in
comparison.
These being?

Ian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,273
Latest member
DamonShoem

Latest Threads

Top