C++ vs. C# surprising revelations

I have been using c# for a while now and at first was very impressed with some aspects of it compared with c++. Ironically and must to my surprise, over time I have become more impressed with c++ and have found some basic problems with c#. Lets look at c# and compare it to (unmanaged) c++.

The Problems
1. Structs

  • C# does a few things wrong here. First of all for the sake of language simplicity simply reusing the class would be the most straightforward mechanism to implement stack vs. heap allocation. You would need a way to specify where a class element is being allocated. Obviously the assignment operator would work differently depending on whether you allocated on the stack vs. the heap. C# also restricts the functionality of the struct preventing derivation which only confuses things more.
  • C++ allows you to use the same structure to specify stack vs. heap allocation, a truly useful thing. After all stack vs. heap allocation is an optimization element, and not allowing the user to use the same code regardless of where he allocates an object is silly. C++ has special syntax to let the user know whether he is accessing from the stack or the heap and this is good.

2. Having the core language specify one behavior for = and another for == with respect to pointers.

  • C# sets the wrong idea by having strings use == not to compare pointers but the actual objects themselves while = always copies pointers. Without overloading == compares pointers. Trying to abstract away pointers to references and then not using them consistently is confusing. What does == do with respect to pointers? Hard to tell if you’re not looking at the source. It seems that if == always compares references (pointers) then it should always simply compare pointers. A .equals or the like would be better suited to testing whether the elements in the class are in fact equal.
  • C++ pointers treat = and == consistently and do not allow overloading and this makes perfect sense. When c++ allows separate behavior for non-pointers this also makes sense. How shallow vs. how deep of a copy is a question best answered by an overload because one size does not fit all. Ditto for comparison here.

3. Not having const support. This is very useful in c++ and c# is less robust without it.
3. The lack of templates if an obvious inconvenience as it makes type safe containers among other things very difficult in c# – this is being fixed for c# with generics and will become a non-issue eventually.
4. The lack of the functionality in a c++ reference. A c++ pointer is basically a c# reference minus the syntactic sugar. A c++ reference on the other hand is guaranteed non-null, which is really nice in a world splattered with if(blah!=null). Sure you can “trick out” a c++ reference but not even making it possible to null check a c++ reference is really nice.

I wanted to add that c# doesn’t generate optimized code like c++ however this has nothing to do with the language itself.

Also the visual studio ide does not allow individual files to be built separately – this is a fallout of metadata.

Some things I dislike have more to do with the libraries than anything else. Having global functions disguised as static members is nothing more than syntactic sugar. Sure you can have ctors for statics in c# and this is a minor advantage, but it is still like putting object oriented makeup on a strictly procedural face. I would rather see the language support autoinstantiated classes that were singletons than this. At least there wouldn’t be arbitrary mixing of “stand alone” functions and true functions that are per instance.

That being said c# (and .net) has a very useful standard library something c++ could take some hints from.

The Good Things

1. C# keeps novices from doing bad things. C# is like child safe locks. It keeps novices from opening the doors when it is dangerous to do so. Some of the many things it keeps safe but yet any savvy c++ programmer would know to use wisely:

  • The preprocessor goes out the window – thank god for the loss of macros – I have reluctantly debugged way to much code using the obfuscation that is macros much to my displeasure – however a savvy c++ coder knows to avoid macros except in truly extraordinary circumstances like the plague.
  • Leaning towards pointers in all cases keeps newbies from falling into c++ traps of non-optimal creation and usage of copy semantics (passing parameters to function that copy expensively).
  • Better syntactic sugar support that makes code a little less arcane. Keywords like abstract, override and others keeps things cleaner.
  • Generating warnings about unintended overrides of non-virtual functions ( c++ should be doing this).

2. C# has some core elements that benefit everyone that C++ should have as well.

  • Garbage collection – obvious but oh so nice. Stroussop has said many times he wants this added to c++ and many tests have shown that in apps with more than a trivial number of allocation that mark and sweep gc is a better performer than typical manual heap based solutions.
  • Robust checking for uninited variables and out of range utilizations. Why the stl can’t at least support debug only range checking in most implementations is beyond me.
  • Meta data support in lieu of header files – no need to qualify this one – in a world without macros why have header files?
  • Static ctors are minor but nice.
  • Having the internal access specifier is nice – c++ could possibly use the javaesque internal to a namespace to implement this hiding.

3. Some C# advantages are much more minor but still nice.

  • Since pointers (aka references) are used far more often in C# and C++ than anything else not needing to specify * when talking about them is nice, and using . instead of the cumbersome -> is also nice. Of course flipping the semantics in c++ would be impossible at this point but I’d rather use * would talking about a non-pointer version of a class and -> to index that same non pointer would be nice as well.
  • Specifying ref when sending a ref to a function so you know it will be modified is nice, not being able to look at a calling function and know what will be modified is frustrating. I would prefer simply using the & operator in c++ or using a plain pointer. The caller doesn’t really care whether the receiving function is using a ref or a pointer unless it is non-const.
  • The syntactic sugar of properties is very nice – its funny how important syntactic sugar can be at times.
  • Event support is nice but I have found it is misused more than properly used. It can create some ugly spaghetti.

4. C# imposes some things that a more irrelevant than anything else including forcing things into classes. How many c# programs have you seen with static functions everywhere – technically this is still an “improvement” over c++ because of static ctors and hiding data elements but still statics are too much like globals for my tastes.

This is really just a few the points I have thought about lately and surprisingly I have found that (unmanaged) c++ and C# both have pluses and minuses. Preferentially which would I work in?

C# in most cases simply because of the robust garbage collection support, lack of header files and extra error checking. But the optimized performance of c++ implementations combined with templates, knowledge and utilization of “pointers/references” vs. stack allocated objects and their consistent behaviors (vs. c# fuzzy mess there), more ubiquitous language support in the dev community, direct interop is asm when needed (rarely of course) are compelling reasons to end up using c++ far more in the future.

If only c++ supported gc standardly as well as metadata of header files or c# supported intelligent stack vs. heap usage, templates and direct interop with native c++, and ideally better performance the choices would be far more clear one way or the other.

I expect the gap to close between the two, although I feel c# will probably be more responsive than c++ in making smart changes, however some things like structs may be difficult warts to hide over time.

7 thoughts on “C++ vs. C# surprising revelations

  1. aaron griffin
    #

    Couple notes:
    a) C# DOES have generics. They have been in the language for years.
    b) C++ does not need garbage collection because allocation can AND should be handled by a paradigm. Have you ever seen std::string leak? It doesn\’t. It uses RAII (Resource Acquisition is Initialization) – meaning this, in short:

    struct Foo
    {
    int* p;
    Foo() { p = new int(4); }
    ~Foo() { delete p; }
    };

    Because C++ contains GUARANTEED destruction, this class will never ever leak. Designing like this proves there is no need for GC at all. Even std::auto_ptr helps here (though auto_ptr sucks, boost::shared_ptr is superior).

    Reply
  2. Steve Riley Post author
    #

    Actually the article is over years old – at the time the version with generics wasn’t yet official.

    I like discreet control in C++ as well. But dangling pointers and/or memory leaks are one of the most common problems seen with shipped C++ code. Many studies have also shown that not dealing with memory manually improve both run time performance and programmer productivity.

    I used to code things by hand in pure assembly. But these days the compiler does a much better job than I could ever do by hand. That same story is coming to light for memory management as well.

    auto_ptr’s are fine, but without reference counting or some other scheme shared pointers eventually end as dangling pointers to deleted memory or going out of scope without deleting the memory they pointed to.

    Reply
  3. Paul Mendoza
    #

    For the most part, the .NET GC is faster than if you coded an application in C++ and managed the memory that way. C++ can be faster but it isn’t easy to consistently beat the .NET GC.

    Reply
  4. Jesse
    #

    You may also nowadays want to look into Herb Sutter’s excellent work on C++/CLI.

    Reply
  5. Steve
    #

    I have been a C++ programmer for several years, using Borland builder. Microsoft mfc development was slow and it was difficult to manage and keep track of pointers and their scope. I have rarely had a problem with managing memory because of the way the structure was setup in Borland, the only time I found a memory leak in my software was when I needed to utilize components not ported over and had to use the MFC to access them, usually a result of not knowing the scope of MFC variables, and internal handling of memory. Memory management for that reason is the one reason I would never go from C++ to C#, GC far more inefficient and still is for a well structured C++ development environment and library (MS C++ developers seemed to want to keep things complex and chaotic, bad coding style if you ask me, no real scope control, object interfaces are too complex, etc… making it a no brainer they will have memory leaks) Add in the fact that JAVA GC sucked, I really did not want to port to C# anytime soon.

    That said C# has many features (at least now) that have made the me make the move at least in the simpler applications. The biggest reasons are notable changes and enhancements to using arrays (foreach, hashed arrays) and a RAD interface that is comparable to Borland’s in many ways.

    If I still need extensive control over memory, I will work in C++, because for memory if you do it right (keep scope in focus), C++ will always run faster and more efficient than running a process to check for scope and then delete memory. And while yes computers are getting bigger and faster, we are running more complex algorithms on them all the time.

    Reply
  6. sardaukar
    #

    Your article totally misses the point of C#. Pointers are weak in C#? Come on, it’s like comparing apples and oranges – the SCOPE of C# is different from C++ and you can’t compare it like this.

    Fact is, C++ is a dying dinosaur, because a time will come when coding in C++ will make your apps 15 nanoseconds faster – but no one will care to pay a more expensive C++ coder to get 0.003% more juice out of an app.

    Reply
  7. The Real Ben
    #

    Business prefers quicker development so any .net platform beats older languages by a long shot.

    C++ is great for systems programming (the really nerdy crap). Even C for that matter (it’s built for speed)>

    In my opinion, C# is a business language for IT apps. C++, C will still be good in terms of electronics, but one day, even those devices will be able to run higher level languages one day. I think programming will be very different than it is now 100 years from now….

    Reply

Leave a Reply