learn C++ or C#

A

Andre Kaufmann

Larry said:
To be fair, this has nothing to do with C++ as a language (which has no
support for multi-threading or GUI whatsoever). You have to separate the
tools from the language itself.

I don't think so. What would C++ be without the standard library ?

And that GUI development is easier in other languages has IMHO something
to do with the language. C++ isn't IMHO fast enough in compilation to be
a good RAD language - at least you don't have the same developing
experience in C++ as in other languages.
[...]
RAII is also vastly superior to "IDispose" and "using" statements. OTOH,

Yes. Using is fine if I hold a resource in a control block, but if the
resource is held by let's say multiple lists, I have to use some kind of
smart pointers to handle the resources efficiently. In C# I can rely on
the GC to free the memory - so far that's fine. But resources should be
freed immediately, if they aren't used anymore.
.NET advocates will point out that the GC takes care of cleaning most
resources so the programmer has to do nothing at all. IMO the C++ paradigm
is still a better design but the reasons run too deep to get into here.


[...]
understand, read, and get right beyond the basics - some things will be
improving in C++0x but it's really too late). The use of #includes and
headers in general (from C) is also a hornets nest of serious problems. Not

I don't think that it's too late, C++ modules could fix many problems.
But since they aren't in the upcoming standard I perhaps have to agree -
it will be too late.

Andre
 
L

Larry Smith

Multi-threading, GUI development is much easier in most of the other
I don't think so. What would C++ be without the standard library ?

It would be another language since it must include the library by
definition. Contrast this to C# whose basic support is primitive (see the
standard for yourself). In any case, the claim that GUI development is
"easier" in C# compared to C++ has nothing to do with the languages
themselves. It's the rich set of classes in MSFT's framework combined with
better development tools that make C# easier (noting that C# is a natural
fit for the framework unlike C++). Provide an equivalent C++ library and
better tools and it will be just as easy (not taking into account the actual
language differences).
And that GUI development is easier in other languages has IMHO something
to do with the language. C++ isn't IMHO fast enough in compilation to be a
good RAD language - at least you don't have the same developing experience
in C++ as in other languages.
[...]
RAII is also vastly superior to "IDispose" and "using" statements. OTOH,

Yes. Using is fine if I hold a resource in a control block, but if the
resource is held by let's say multiple lists, I have to use some kind of
smart pointers to handle the resources efficiently. In C# I can rely on
the GC to free the memory - so far that's fine. But resources should be
freed immediately, if they aren't used anymore.

The "using" statement is ugly compared to RAII. Moreover, in theory your
unmanaged resources may never be released if you neglect to call
"IDisposable.Dispose()". Other problems also exist with this pattern.
.NET advocates will point out that the GC takes care of cleaning most
resources so the programmer has to do nothing at all. IMO the C++
paradigm
is still a better design but the reasons run too deep to get into here.

[...]
understand, read, and get right beyond the basics - some things will be
improving in C++0x but it's really too late). The use of #includes and
headers in general (from C) is also a hornets nest of serious problems.
Not

I don't think that it's too late, C++ modules could fix many problems. But
since they aren't in the upcoming standard I perhaps have to agree - it
will be too late.

The core language is in place. Enhancements won't change that. The problems
inherent in C++ will remain forever unless it morphs into a different
language (but then it won't be C++ anymore).
 
G

Giovanni Dicanio

"Peter Duniho"
In C++, RAII provides a convenient way to deal with that, and in C#, the
"using" statement does the same. You may prefer one syntax over the
other, but I personally don't see a difference between the two that would
justify an argument of superiority one way or the other.

Destructor and "scope" syntax in C++ is cleaner, simpler and more elegant
than C# bloated 'using'.

Moreover, there is big difference between C++ RAII and C# "using".

In Andre's words:

<quote>
Using is fine if I hold a resource in a control block, but if the
resource is held by let's say multiple lists, I have to use some kind of
smart pointers to handle the resources efficiently.
</quote>

For example: I think that there is nothing like shared_ptr in C#.
With shared_ptr you can have a *deterministic* resource manager, and you can
wrap also non-memory resources in classes and store shared_ptr to these
class instances into STL containers, and that works fine and is very elegant
and simple.

And there are also intrusive smart pointers, you may consider Eugene
Gershink's implementation here:
http://www.gershnik.com/articles/refcnt_ptr.asp

BTW: I'd like to make it clear that I'm saying neither that C++ is better
than C#, nor that C# is better than C++. Simply, both languages have pros
and cons.

Giovanni
 
L

Larry Smith

In C++, RAII provides a convenient way to deal with that, and in C#, the
"using" statement does the same. You may prefer one syntax over the
other, but I personally don't see a difference between the two that would
justify an argument of superiority one way or the other

That's hardly a valid argument, considering that RAII requires no "using"
statement whatsoever. This alone justifies an argument that there is a
difference in favour of C++ (in contrast to your assertion).
Larry's claim of "vastly superior" seems particularly baseless. Vastly?
Pure hyperbole.

Point conceded. Scratch the word "vastly".
 
D

David Wilkinson

Peter said:
This distinction has nothing to do with the _language_. If the OS was
entirely garbage collected, then these "non-memory resources" wouldn't
be an issue. They would be managed the same way memory is in .NET and
you'd never have to worry about disposing them.

Now, with certain types of objects you'd still have to deal with
closing, flushing, etc. But that's not something that RAII inherently
solves; it just happens that C++ classes can take advantage of that to
handle those operations. The OS API itself isn't based on C++ and
requires the program to deal with managing those operations.

In C++, RAII provides a convenient way to deal with that, and in C#, the
"using" statement does the same. You may prefer one syntax over the
other, but I personally don't see a difference between the two that
would justify an argument of superiority one way or the other. Larry's
claim of "vastly superior" seems particularly baseless. Vastly? Pure
hyperbole.

Not only is the "using" mechanism less convenient/elegant for the client of the
class than RAII (not to mention the possibility of forgetting to do it), but a
C# Dispose'd object can still be used (unlike a C++ object that goes out of
scope or is delete'd). This places an additional burden on the writer of an
IDisposable class.

IMHO, any use of a Dispose'd object should automatically cause a
"ObjectIsDeadException" rather than relying on the author to test and throw an
ObjectDisposedException in every method.
 
A

Andre Kaufmann

Larry said:
It would be another language since it must include the library by
definition. Contrast this to C# whose basic support is primitive (see the
standard for yourself). In any case, the claim that GUI development is
"easier" in C# compared to C++ has nothing to do with the languages

The RAD tools have to parse the source code, which is more complex in
C++ and therefore there aren't that much (good) RAD tools for C++ or
they feel somewhat sluggish.
So let's restrict the "easier" part on development of good RAD tools not
on using them.
themselves. It's the rich set of classes in MSFT's framework combined with
better development tools that make C# easier (noting that C# is a natural
fit for the framework unlike C++). Provide an equivalent C++ library and
better tools and it will be just as easy (not taking into account the actual
language differences).

With easier I meant the whole development experience - so it was perhaps
somewhat misleading to use the word "easier".
With development experience I mean Intellisense / refactoring / fast
compilation and so on.

There are GUI frameworks supported by different languages including C++:

C++ (/CLI): WinForms, VCL
C# : WinForms
Delphi : VCL

But IMHO the development experience in C#, Delphi is better than in C++,
just because of the compilation speed. It makes a huge difference if you
wait multiple minutes after having touched the GUI or just a few seconds.

Andre
 
A

Andre Kaufmann

Peter said:
]
I don't disagree that RAII allows for an object to simply "disappear"
when the scope is exited, but this is how "using" works in C# too.
Variables declared in the "using" statement are valid only for the scope
of the block of that statement.
[...]

For scoped resource handling I think "using" is a good alternative for
RAII. But I miss RAII sometimes in C#:

E.g:

list (a) - holds a file object (f)
list (b) - holds the same file object (f)

When I remove (f) from list (a) I have to check if list (b) holds the
file object too or rely on GC to close it - but I think that wouldn't be
a good idea, since the file would be open, till the GC has disposed the
object.

In C++ I can use RAII smart pointers to ensure that the file is closed
as soon as it's not used anymore. In C# I have no automatism to handle
this.

I see that there are benefits in GC over RC = reference counting, but
IMHO both are relevant:

GC - for memory
RC - for resources


Andre
 
D

David Wilkinson

Peter said:
I was comprehending your post until "or is delete'd". There's nothing
in C++ to stop someone from trying to use an object that's been deleted,
and depending on how the memory was allocated and what the class does in
its destructor, doing so might even work for awhile.


I don't see how it's any more burden than already exists in C++.
There's no requirement that a disposable class actually catch
post-disposal uses. It's nicer, but then so too would it be nicer for a
C++ class to catch uses that occur after destruction. And I think it's
easier for a C# class to do so, because the object is still actually
allocated and the code in the class can behave predictably; in C++,
sometimes using an object after destruction will fail immediately, and
sometimes it won't.


I don't disagree that RAII allows for an object to simply "disappear"
when the scope is exited, but this is how "using" works in C# too.
Variables declared in the "using" statement are valid only for the scope
of the block of that statement.

And just as in C#, the reference to the variable declared in the "using"
statement could "escape" by being passed to something else, so too could
a pointer to a stack-allocated C++ object escape. RAII in C++ doesn't
actually guarantee that you can't use the object reference after the
object itself has been destroyed. It just ensures that the object is
destroyed outside a particular scope, just as "using" does.

If anything, at least with a garbage collecting system, you know that if
you have a reference to something, that's a valid reference. The object
itself might be in an unusable state, but it will always be able to tell
you that one way or the other.

<snip>

Pete:

Well, I think C++ programmers (even bad ones) are generally aware of lifetime
issues, whereas C# programmers can be lulled into a sense of false security by
the "garbage collector will take care of everything" mindset.

I just find this notion of the "half dead" object rather disturbing. Surely it
would have been possible for the C# language to be defined such that use of a
Dispose'd object automatically throws an exception?
 
J

Jon Skeet [C# MVP]

Just because an object is done with its unmanaged resources, that doesn't
mean to me that it's "half-dead". It's just done with the unmanaged
resources. If a class wants to allow disposal prior to actually being
done with the object and still permit certain operations on the object
after disposal, that should be its right.

MemoryStream is one example, by the way - you can still call ToArray on
it after closing it as a stream.
 
B

Ben Voigt [C++ MVP]

MC said:
Yes... the big difference is that with C#, errors manifest themselves
as incorrect output or recognizable error messages rather than random
crashes or memory leaks.

C# is just as capable of hanging, leaking memory, and having
non-deterministic behavior as C++. And most C# developers have bought the
company line that .NET prevents memory leaks so they haven't the slightest
clue how to begin looking for one.
 
B

Ben Voigt [C++ MVP]

A simple example:
How do I ensure in C++ that I have successfully overridden a base
class virtual function and that the compiler throws an error if the
base class implementation has changed ?

You can't do that in any language I'm aware of, so it's a non-issue. Did
you mean "error if the signature of the function in the base class has
changed"?
 
B

Ben Voigt [C++ MVP]

Peter said:
Purely subjective. That sort of claim has no place in a technical
discussion.

It's quite objective. In C++, the burden is on the library developer, the
user needs no extra syntax to benefit from automatic cleanup.
RAII doesn't _inherently_ support "smart pointers", nor does a garbage
collecting system prevent one from implementing "smart pointers".

As I pointed out before, in a 100% GC-ed system, "smart pointers"
become unnecessary anyway. But in a mixed system (i.e. pretty much

Nothing could be further from the truth. Lazy (or deferred, if you prefer)
cleanup breaks access to shared resources, and does so
non-deterministically.
any current platform), it's entirely possible to implement "smart
pointers", and they can work in a very similar way to that
implemented with RAII.

No, in C# it's not possible to create an object that automatically performs
cleanup when it becomes unreachable. You can only do so (1) manually, or
(2) when its memory is reclaimed.
 
B

Ben Voigt [C++ MVP]

Peter said:
You save a whole line of code. Wow! Yup...that definitely outweighs
any advantage that garbage collection has with respect to simplifying
and improving the robustness of memory management. After all, that's
what programmers really care about. I'd much rather save a line of
code than make it more likely that my code is correct.

The C# way is brittle. If C# let you use a using statement with types that
don't support IDisposable, then it would be better. But right now, adding
IDisposable support to an existing class is always an impermissible breaking
change.

In C++, you can add a destructor without any changes to the code which
references the class.

That's a much bigger issue than saving a single line of code.
 
B

Ben Voigt [C++ MVP]

Peter said:
I was comprehending your post until "or is delete'd". There's
nothing in C++ to stop someone from trying to use an object that's
been deleted, and depending on how the memory was allocated and what
the class does in its destructor, doing so might even work for awhile.

C++ delete calls the implementation of 'operator delete' after running the
destructor, which can mark the memory with a pattern (or on some CPUs, even
set up data breakpoints to trap any future access to that memory) which in
debug builds would detect use after free. You can use something like
electric fence which will deallocate the segment, generating a segfault on
any future access to that object. All of which can be done without any
changes to the class being protected.

So no, these aren't "in C++", because one of the prime ideals of C++ is "you
don't pay for what you don't use". You turn on these features during
debugging, and perhaps in extremely critical environments where failure
detection is more important than efficiency you might leave them on in the
release build. In all other circumstances, you convince yourself through
thorough testing that these sorts of bugs have been eliminated, and disable
the checks.
 
A

Andre Kaufmann

Peter said:
On Thu, 24 Jul 2008 12:30:34 -0700, Andre Kaufmann

[...]
But you can include reference counting in the C# object if you want.
You can even implement a "smart pointer" class that uses Dispose() to
decrement the counter and call Dispose() on the wrapped object if it
reaches 0.

I can include reference counting, but I can't use smart pointers. I
prefer GC memory handling, but for resources GC can't be used
effectively, because often resources have to be released directly.
I do a lot of multi threaded programming, there I permanently have the
need of some kind of reference counted resource handling.

[...]
But there's nothing about C# that precludes using that
technique if you find yourself i

If you could add methods to value structures in C# I would agree. But
currently in C# you have to either use a temporary object in combination
with using or call the AddRef / Release functions by hand.

Perhaps it wouldn't be a good idea to add the complexity of C++ which
allows RAII to C#, but some kind of simple automatism would IMHO help too.

E.g. the temporary objects could be replaced by some kind of using which
calls specified methods of an object.

Pseudo code:

MyObject o; // member variable
....
autocall(o) --> calls enter / leave methods automatically
{ // call o.enter()
} // call o.leave()


Andre
 
L

Larry Smith

Yes... the big difference is that with C#, errors manifest themselves
At least you KNOW there's something wrong when you get a random crash ...

Assuming it does crash. C++ can not only suffer from the same "incorrect
output" as C# (and to a potentially much greater degree), but it can also
result in very serious (and potentially "random") problems that may not
manifest themselves until long after the problem has occurred (in ways that
C# just isn't susceptible to). And you may never even notice it. You may be
filling your DB with garbage, generating invalid reports, displaying
incorrect information for users, etc., but it may not come to anyone's
attention depending on the nature of the problem. And if (when) it does, it
may be incredibly difficult if not (practically) impossible to track it
down.
that incorrect output you get from your C# program is really much more
dangerous.

I think you and Larry and others here blowing the C# trumpet are vastly
over-stating the case about C++ being hard to use and hard to get right.
The fact is that bad programmers will write bad code in any language, and
if you want good code you have to employ good programmers. Once you have
those your problems will start to go away -- whatever language you are
using.

Of course, you need good management, too. Bad management and irrational
budgetary constraints can ruin a project just as easily as bad
programming.

Lol. You must have just graduated.
 
L

Larry Smith

I also have some serious pet peeves. Why didn't they permit local
I think the answer to that is "it looked too hard at the time" ... and
IIRC
that constraint is to be removed an some future version of the standard.

Too hard? Maybe too little time to work out the details at the time but it
had something to do with the binding rules according to Stroustrup. I don't
recall the limited details he provided off-hand.
I think it's /only/ the very experienced developers (and those who aren't
but think they are -- which is more worrying) who "continuously bend their
minds out of shape" looking for new ways to use the expressive power of
the
language. These are the library builders, the Boost developers, the
Alexandrescus of the world ... most C++ programmers just /use/ their work
and are grateful for the way that it makes their lives easier and more
pleasant.

Most code in the real world is mediocre at best but usually much worse. It's
usually indicative of people who don't have their heads wrapped around the
language and how to program in general (opposed to pushing the limits of the
language). Even very experienced (skilled) programmers still have to
exercise a lot of caution and deal with complex issues not common in other
languages (not always but frequently enough). Most C++ programmers may be
"grateful" but the majority are causing serious problems for their
companies, their colleagues, and their users. Most of them function in a
state of ignorant bliss and management usually doesn't understand the scope
of the problem.
 
A

Andre Kaufmann

Peter said:
On Thu, 24 Jul 2008 22:43:52 -0700, Andre Kaufmann


Why not?

Not in that way as they are used in C++.

E.g. if I assign one smart pointer to another in C++ the reference is
incremented. In C# I would have to use a method for the assignment.
But I can't prevent one smart pointer accidentally be assigned to
another one in C#.
So I don't see that much value in smart pointers in C#, I then rather
would prefer the AddRef method directly and not using a smart pointer.

For what it's worth, I've done a fair amount of multi-threaded
programming in C# without needing ref-counting.

For example in the following architecture:

A simple shared buffer holding memory and resources:

-> Thread #1
---> [ReceiverThread] - passes --> -> Thread #2
-> Thread #3

The buffer is passed to multiple receivers which "do something" with the
buffer. After the last thread has finished it's operations it should
release the buffer and store it into a central pool for reusing and
should additionally release eventually used resources immediately.
How do I know if the last thread has finished ?
Not that I agree that ref-counting can't be done in C#, but I've found
that in many cases, what's really needed is a different way of looking
at the problem.

Yes, reference counting can surely be done in C#. But I don't see how I
could use reference counting with smart pointers in C# ---- outside of a
control block.
[...]
But there's nothing about C# that precludes using that
technique if you find yourself i

If you could add methods to value structures in C# I would agree.

I don't know what you mean here. What methods do you want to add? To
what structure? How would that help?

A structure is a value type in C# and therefore copied on assignment and
immediately "freed" if the control block is left.
If I could add an destructor and overload the assignment operator I
would have a possibility to implement smart pointers like in C++.

How is a smart pointer not a temporary object?

Yes, that's the point. I know how to handle it temporarily in a control
block, but when the smart pointer is added to a list of smart pointers
and removed from the list I have no possibility to "force" the automatic
release of the reference.
I have to remove the smart pointer from the list and then manually call
release. What's the point of a smart pointer in this case ? I could
rather use the reference counted object directly
[...]
Why not just create a smart-pointer-like class or struct that does that
with the "using" statement? Adds a ref when the object is created,
decrements the ref on disposal, zero ref-count causes disposal of the
wrapped object.
Maybe I'm just being obtuse, but I don't see what the big problem is.

I only have the feeling that just creating a new object to automatically
call methods of another object in the Dispose method is somewhat
overkill. The GC is fast, but why should I add pressure to it, by
permanently allocating temporary objects ?

I agree It's no big deal if the temporary object is created rarely or
held for a long time.

But additionally a smart pointer should behave like another ordinary
pointer, with additional functionality that is under my control.

Andre
 
A

Andre Kaufmann

Ben said:
You can't do that in any language I'm aware of, so it's a non-issue. Did
you mean "error if the signature of the function in the base class has
changed"?

Sorry yes - the signature - function declaration - not the definition or
code inside the function itself.

Andre
 

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

Top