Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Why C++ is vastly superior to C (povusers.org)
48 points by tree_of_item on May 14, 2011 | hide | past | favorite | 119 comments


When the argument is that C++ has too many features that interact in unpredictable ways and are virtually impossible to get right, arguing that C++ is superior because it has more features is perhaps a fine argument in some hypothetical universe in which the primary objection to C++ is that it is missing features, but by failing to grapple with the points raised by the opposition in the real universe, you will fail to convince anybody. Everybody already knows all of these features, they're practically in the canonical Introduction to C++ pitch, and they still don't think C++ is great. Maybe you need to spend a bit more time listening more carefully to why; you certainly need to if you expect to talk anybody out of it.


What are some of these C++ features that interact in unpredictable ways? Just curious.


Implicit conversions come to mind. They don't need to interact with anything to be confusing.

Consider this program:

    #include <iostream>
    using std::cout;
    using std::endl;

    struct C {
        int x;
        C(int _x) : x(_x) {}

        operator bool() const { return 0 != x; }
    };

    struct D {
        float f;
        D(float _f) : f(_f) {}

        operator bool() const { return 0.0f != f; }
    };

    int main() {
        C c(9);
        D d(2.0f);

        if (c == d) {
            cout << "Equal" << endl;
        }

        return 0;
    }
g++ 3.4.4 doesn't so much as warn that something is fishy here, even with -Wall.

Not only that, but c and d are considered to be equal.


You don't get a warning because the program is doing exactly what you asked it to do. You said a C with x = 0 is equal to 'true'. And you said a D with f = 0.0 is equal to 'true'. By transitivity of equality ...


c and d are considered equal, you have overridden the boolean operators, what the code is actually calling on your if statement is:

c.bool() == d.bool()

In this case both will return true since they are non-zero, and thus the statement would be

1 == 1

Which is true; the compiler did exactly as you told it to do.


Maybe it's just coming from a dynamic language, but it appears that you've overridden the bool operators to always return true. (except when you pass in 0 and 0.0) If you redefine how two structs of different kinds are compared, who is the compiler to say it's a problem?


In most dynamic languages 0 is false and anything else is true but it normally wouldn't use that information to coerce two values of different types to booleans before comparing them.


I'm only aware of php and javascript equating 0 to false. But at any rate in this case it's not equating 0 to false, it's comparing non-zero to zero and returning true. (as it should)


In C, 0 evaluates to false.


In C++0x you can make those operator bool() explicit. Shouldn't have been there in the first place, and you still have to learn the difference between explicit and non-explicit operators, but at least now there is a way of making things behave.


Even if they were explicit it wouldn't have "solved" his issue. Since he is using them in an if statement the C++ compiler would have considered that an explicit conversion anyway in C++0x mode.

I don't have a C++0x compiler handy, or I would test it, but I do believe explicit is only meant for cases such as this:

a + 1;

where a has a bool() operator that returns 1 or 0, in the old mode if there was no way to get a to be a number it would look at the operator bool() see that it returns a number and use that. Using explicit on the bool() operator would make that illegal and most likely a compiler error.


Yes, several people have already piled on. But if the compiler didn't say "Equal", then I would be claim it's confusing/inconsistent.

Are you saying that the funtion YOU wrote to convert C/D to a bool shouldn't be invoked when YOU are using C/D as booleans?


It's perfectly logical to use those functions when comparing them as booleans.

But it's confusing that they're being used as booleans at all. They're converted because it will let the types match even though the conversion doesn't make much sense.


http://yosefk.com/c++fqa/defective.html isn't strictly limited to answering that question, but it touches on it a lot.

I know I'm flinging links around a lot here, but, well, this is all well-covered ground.


Most of the points mentioned in that particular link pertains why both C and C++ are inferior to languages like LISP and Python which have garbage collectors, weak type system and the like.

The bitching about bad compile time errors has been mostly fixed in clang.

Then only _inconsistency_ (in the correct sense of the term) in C++ I am aware of is the unordered initialization of static objects. So if you have "class A { ... A () { } };" and have a "A foo;" declared somewhere with static linkage, it can be hard to pin down exactly _when_ that constructor will be called. It will be called before control is transferred to main, but you may want even finer control.

If you have noticed other inconsistencies I'd love to know.


> The bitching about bad compile time errors has been mostly fixed in clang.

Yes, IOW, it is a compiler problem, not a language problem. Because one particular compiler is horrible on error presentation doesn't mean that the language is bad.

> declared somewhere with static linkage, it can be hard to pin down exactly _when_ that constructor will be called.

The language doesn't define it on purpose. The language leaves it to be defined by the implementation because it goes a little beyond the purpose of the compiler. The compiler transforms C++ source into object code. You can have multiple objects linked together into a single binary, and this linkage is very platform and operating-system dependent. C++ is already horribly difficult to implement correctly; if the language were to define an order for static initialization, it would be stepping on the operating system domain, and make it even more difficult to implement on some systems.


I guess that's why the Google C++ style guide lists using static non-POD types as a no-no. :)


often it's the implementation for certain platform that limits you, choices of what the C++ supports decides by the platform vendor - for example exceptions, rtti, or even up to date compiler.

another provblem arises due to the decoration, mangling of c++ symbols (while c externs do not have this problem), and sometimes this is problem even with two different versions of the same line of compiler

another one is the runtime incompabilities (exceptions again) and different compilers.

this problem is so bitchy, that if you have to develop plugin for maya, motion builder in c++, you have to use the same compiler the products were compiled with, which is not the case for a lot of the infrastructure, os out there...


Copy constructors are bad. Variable assignment should not be a user defined behaviour.


<fx: sigh>

For some things, C++ is better than C. For some things Lisp is better than either, and for yet other things, Python is better than them all.

Why are people so insistent on declaring their view is absolutely right, with no arguments, everyone else is wrong, and that one language will rule them all?

Trust me. For some things I do, C is vastly superior to C++, but I'm not going to try to convince everyone that C is better than C++ (or anything else) for everything that anyone wants to do.

That would just make me look stupid.


I think much language criticism miss the non-technical context which influences which language is the best tool for the job. We are good at providing technical arguments (Erlang is fun if you need concurrency, C is cool if you need to get close to the metal), but there are important non-technical issues.

Things like: How many people is on the team who have to work on the code? How big is the turnover among the developers? How experienced are they? How long is the code going to live? Will some people have to jump in and fix bugs in the code on short notice?

For example, I have noticed that I prefer a nice clean dynamic language like Python when I know I am only person on the project. But in cases where I had to work on and improve code of a dubious quality, I much prefer it to be in C#, since type analysis makes it a lot easier to figure things out and refactoring in a safer way.

To put it another way: I like to work with nice clean code in Python or Haskell, but when I have to work with bad code, I prefer to work with bad C# code.


I think you know you've cracked when you prefer bad C# to clean Haskell.


Bad C# over bad Haskell, I think.


I have a... secret wish? private fantasy?... where I take a moderately complicated problem and outsource it to a known bad outsourcing company, but rigidly require that they write it in Haskell. Just to see what pops out.


Edited to be less ambiguous :)


Are you saying that you can do better type analysis in C# than in Haskell?


Indeed.

This article is more "why C++ makes this particular program easier to write" and is in no way any proof that C++ is better than C.


On the other hand, I don't think I've ever written a program that doesn't use containers, manage memory, and handle errors.


C and C++ have considerably overlap in use cases, which is what makes this argument valid.

Comparing C or C++ to Ruby or LISP is stupid.


Directly, yes.

But comparing C or C++ to C# isn't completely off the mark. And comparing C# to Java isn't crazy either. And once you're at Java, there are plenty of cases where a comparison to Ruby or Lisp makes sense.

So anytime a use case starts in Java (web, mobile, and desktop applications), I think there are very good comparisons to be had on which direction to go.


I don't think this article is about declaring C++ the ruler of all languages.

If you have an example of C being a better fit for a problem than C++, feel free to share it.



The author of the OP also has a response to your second link:

http://warp.povusers.org/OpenLetters/ResponseToTorvalds.html


Embedded systems, 128 bytes of RAM. I really do just want portable assembly.


But you don't have it, unfortunately. At that level C is just as unsuitable. Time to break out your assembler. ;)


To put that in perspective, 128 bytes is an x64 program's stack's red zone. :D


> If you have an example of C being a better fit for a problem than C++, feel free to share it.

http://www.kernel.org/pub/linux/kernel/v2.6/


I've found that whenever someone argues "X is best", they've only worked in projects where "X" makes sense for them. At a start up a couple of years ago, we had an intern that was all hot and bothered over C++ and boost. After he expanded is horizons to web development and investigating scripting languages, he really enjoyed Ruby.

It depends on what you are working on, the libraries and tools available, and your comfort with what languages fit that paradigm.

I use C++ and Java on a regular basis now, but prefer C for systems programming, and Python for general web/scripting stuff.

Since we need to have a nit with C++ for this thread, can someone explain to me how debugging in C++ while using templates is superior?


The answer to your question is "use Visual Studio." ;-) Or, at least, use clang. The gcc stack is pretty poor at dealing with templates, and its debugger is pretty baroque.


+1 Use the right tool for the right job is the proper approach. Right tool depends on your project requirements.


This post boils down to "Take C, add support for OO, a crapload of new syntax, standard library that 10x as large and ta-da! you can find problems which have simpler solutions than in C."

There's a great post by Linus Torvalds about C vs. C++ in the kernel. Some excerpts:

"My point being, that C++ adds absolutely nothing interesting."

"C++ is a mess. There's no design. It's just "add crud on top of C". And the crud isn't even meaningful, much less does it have a design. It's totally and utterly random.

It started out random, now it's randomness that gets added to by a committee."

Whole thing: http://www.realworldtech.com/forums/index.cfm?action=detail&...


The author of the OP has a pretty well written rebuttal to everything Torvalds has said about C++:

http://warp.povusers.org/OpenLetters/ResponseToTorvalds.html


I looked at the rebuttal and I couldn't make past the part where he argues against this point - It's made more horrible by the fact that a lot of substandard programmers use it ... Even if the choice of C were to do nothing* but keep the C++ programmers out, that in itself would be a huge reason to use C*

As someone who had substantial exposure to interviewing and hiring C and C++ programmers to add to a team of 250 it was bloody obvious that a lot of pure C++ programmers are the pompous know-it-alls who think they know C++, while C people are those with far more realistic self-assessment who actually do know the language. Linus got it absolutely right.


That article is not very informative, and spends a lot of time characterizing Linus as someone with the “C-hacker syndrome.”


I find the article to be vastly more informative than most of Linus' posts about C++, which usually read more like rants than well informed criticism. He does not characterize Linus as a "C-hacker", Linus does that himself by posting an opinion about C++ that completely lacks substance.


The OS-level stuff I work on is in C. C++ would be a disaster. When you are working in environments that /define/ the run-time of your system: Interrupts, exceptions, memory management, threads and so on, the extra crud is actively harmful.

That said, when I'm working at the application level, C++ is better at a lot of things.

Finally, my cow-orkers and I have an agreement that if any of us start doing template metaprogramming, that that person will be shot.


The problem with C++ is that the language is too damn big. This results in most programmers only learning really well a subset of the language.

Unfortunately, different programmers end up with different subsets.

I'd like to see some de facto standardization on subsets. For instance, there could be Basic C++. When programming Basic C++ you use it like C with the following C++ features added: constructors, destructors, references, std::string, and maybe the STL collections.

Simple Object C++ could be Basic C++ plus single inheritance.

The on top of that, we could add things like multiple inheritance, operator overloading, templates, and so on.


Most projects have a set of coding guidelines. I don't see why it cannot specify things like: "Don't use operator overloading!".

Google does, for one thing.

Without discipline both C and C++ will blow you up completely. With some discipline both the languages are manageable, and C++ more so; which is what the OP points out.


that's exactly right and correct. any language can be screwed up without descipline, and understanding of the solution trying to be implemented. me for example, put comments in code that what direction of design, execution path is taken to correct less efficient idioms. so, at a later time, new code can be added with some direction. this prevents the urge to copy and paste by the new guy.

coding guidelines are also to include programming idioms, primitives, to use and build the solution around it.

for c++, c and others i wrote many of guidelines, and seeing the benefit later i can say the above.


Apart from "use the right tool for the job", I always did wonder how C programmers cope without the STL containers: std::vector, std::list, std::set, std::map etc.

Sometimes I need to map a string to a list of numbers. std::map<std::string, std::vector<int> >. Done. All memory allocation taken care of for you as well - nothing to leak. In C, how do you get by? You either have to reinvent a red-black tree each time you want that, or use some kind of type-unsafe macro horror, or just not use that data structure.

That seems to be a significant point of the article as well. Any C programmers care to enlighten me on this? Nowadays I couldn't code for long in C without thinking "screw this, I want a vector" and going back to C++.


Fair point, but in systems programming where C is used a lot, the 'system' often/usually has the abstract data types you need, or you're in a lower level enough environment that you want your own custom/hardware specific solution.

Crude example: http://kernelnewbies.org/FAQ/LinkedLists


If you don't like macros (which are used quite a lot for this sort of thing - e.g. http://fxr.watson.org/fxr/source/sys/queue.h), void pointers and function pointers go a long way too. Nobody's writing red-black trees from scratch for every project, really.


Counterpoint to the C++ fragment in "Error handling" section:

  void foo()
  {
    Matrix *a = new Matrix(1000, 1000);
    Matrix *b = new Matrix(1000, 1000);
    
    delete b;
    delete a;
  }
Pretending exceptions solve error handling gets you a big fat zero. Look at boost: despite being written by C++ experts and held up as an excellent library (which it is!), it contains exception-unsafe portions. Why? Total exception safety is just as hard as the original error handling problem.


Counterpoint to your counterpoint:

  void foo()
  {
  	typedef std::auto_ptr<Matrix> matAP;
  	matAP a(new Matrix(1000, 1000));
  	matAP b(new Matrix(1000, 1000));
  }


I don't think it's because the Boost guys thought it "too hard". Having seen/used some of those libraries, I'm 100% sure they can handle the alleged "hardness".

C++ in general values performance over safety almost everywhere (just like C). That's probably why they made certain parts exception-unsafe.


I know that C++ has some pretty neat features, but I feel comfortable and productive enough in C. I have never really felt that there was anything in C++ that I just had to have.

If I need to something higher level there are plenty of choices of that already, and C is a great language for extending applications done in a higher level language.

I think that the author has some good points. but I think both languages have the places where they excel.

To say that one is "vastly superior" to the other is a mistake. If C++ was really "vastly superior" to C then why are so many people still using C and using it productively?


> If C++ was really "vastly superior" to C then why are so many people still using C and using it productively?

Why are so many people using Java (perhaps even more than C and C++ combined)? Does it make a good language? Absolutely not. In the case of such simplistic languages as C and Java, it's their simplicity that makes them a popular choice.

Productivity: I am not sure all the C folks are as productive as they could've been if they switched to C++. Same people.

The complexity of C++ is not only in the amount of new concepts compared to C, it is also in greater risks of producing bloated binaries. Too much knowledge and caution is required to keep C++ code maintainable in this regard. That's a drawback, but if you ask me, I'd never give up RAII, implicit destruction and exceptions for C; I'd rather understand them better in order to use them properly.

And finally, the article would look much nicer without the insults closer to the end.


"Why are so many people using Java (perhaps even more than C and C++ combined)?"

Well, one contributing factor is that a lot of universities now have a heavily Java based curriculum (turning their CS programs into vocational schools, but I digress).

Another contributing factor is that Java has managed to carve itself a niche in which it is used extensively ("enterprise" applications - with all of the wonderful ambiguity that the word "enterprise" carries nowadays).

One more thing in Java's favor is just simple momentum. There are a lot of Java libraries that just plain work (and some work extremely well). There are a lot of applications on the corporate side that use Java.

Regardless of whether you or I like the language or not, Java has apparently proven itself useful to a broad swathe of people. It may not be an exciting language, but then neither is Cobol and it still exists as well (and puts food on quite a few tables).

Then there is the venerable JVM, which is actually an amazing piece of software engineering that has enabled the development of a wave of innovative new languages. Of course, one of the features of many of these new languages is the ability to drop down into Java for speed (now before anyone starts sneering, Java is actually not doing to bad on that front right now).

"Does it make a good language? Absolutely not."

Perhaps not in your opinion, but their are others who are quite fond of it. That's the problem with these type of pronouncements. What makes a "good language" varies from person to person.

Disclaimer: I have used Java for some small projects in the past - I may be somewhat biased.

Edit: Embarrassing grammatical flaws.


I know Java is practical within certain contexts and for certain class of people, but our judgement of what's good or bad in general shouldn't really be a matter of taste and preference. Are we an engineering discipline or what?

What we call a matter of preference is actually things that go beyond engineering. We may have emotional ties to programming languages ("I love Java", "I hate C++") because of job security, because of often subconscious fear of inability to learn new stuff, and so on. We should clean up the table from the psychological aspects of the matter and look at what's left: that's how powerful and how clever a language can be in the hands of a good developer.

Java is a terribly verbose and an embarrassingly simplistic language. C is simplistic and can be considered dead the day C++ compilers catch up with speed and memory allocation, which will make it suitable for embedded programming too.

(And BTW, I don't mind JVM, it probably is a fantastic piece of engineering, except... for reasons I don't understand very well, a simple "Hello world" application written for JVM can take seconds to load and execute. I've heard a thousands reasons none of which made much sense. As well as promises JVM will be improved in the future. First time I heard this was 15 years ago, still no progress.)


"C is simplistic and can be considered dead the day C++ compilers catch up with speed and memory allocation"

Those really are not the problems that are most pressing with C++ in the embedded field. Comparable speed is rarely noticeably different provided you avoid certain key things, and you can always just swap in a new allocator if you want.


By memory allocation I meant memory usage by the compiler itself. Plus libstdc++ which is not easy to get rid of, and if you do dump it, you at least cut off C++ exceptions.

I once switched from C++ to C because g++ just couldn't handle the module even having all optimizations turned off. That was a huge automatically generated C module with thousands of functions. A rather rare situation but showed very clearly that C++ is not almighty.


Compiler speed/memory use are generally entirely irrelevant with embedded stuff. If you're natively building on your tiny target instead of cross compiling from your beefy workstation, you're doing it wrong.

No, for the very real issues with C++ in small installations, you will have to look at the language itself.


Believe it or not, it was on a beefy workstation (I think the number of functions was tens of thousands actually). Of course I could have split the module or find some other solution, but the thing was, switching to C solved the problem. More importantly, I was able to switch on compiler optimizations.


I am not getting what makes this any different from any other very large build then.


The size of a single module with say 50,000 automatically generated functions 3 to 10 lines each. You want to try it? ;)


"our judgement of what's good or bad in general shouldn't really be a matter of taste and preference. Are we an engineering discipline or what?"

You know what. It's a funny thing, but as I was typing my response to your original post, I actually said this exact same thing to myself, and I started to think. It would be incredible if there was some non-emotional, non-touchy-feely way to get at the value of one language vs another. But then programming language choice just seems to be an inherently "feel" based decision...

"We should clean up the table from the psychological aspects of the matter and look at what's left: that's how powerful and how clever a language can be in the hands of a good developer."

This is one of the things that I thought of, but then there are so many demonstrations of people using all kinds of programming languages to do things that are incredibly clever and powerful.

Sometimes I like to just go through open source projects written in programming languages I am not extremely familiar with. I just want to get a taste of some of the myriad of programming styles and techniques that are out there. The different ways of looking at the same problem.

Even if I disagree with the method used, it is always eye-opening to see other ways of doing things - even some that may be vastly different from anything that I have ever seen before (my first time looking at Haskell comes to mind). I like to understand how and why different developers choose the routes that they choose.

I don't know, but to me it seems that, in a way, it is good that there is no emotionless method for rating languages. To declare one language as being definitively better than all others seems to me that it would be a tremendous loss. There is some value, I think, in having a diversity of "good" languages just for its own sake.

As to the simplicity of a language, well, to some people simplicity in a programming language is a beautiful thing, but then, the problem is that what constitutes simple is also a thing that varies from developer to developer. Perhaps the diversity of languages is a natural development from the diversity of programmers?

I think about Ruby. You know, when Matz describes why he created the language, he says that he wanted to create something that felt fun to develop in - fun for him. The fact that other people just happened to like Ruby was an unintended side effect.

I think that most people create a programming language with a similar type of outlook. They, either purposefully or subconsciously, try to build it to achieve a certain "feel". Perhaps it is this "feel" that makes a good developer powerful and clever with a language.

"for reasons I don't understand very well, a simple \"Hello world\" application written for JVM can take seconds to load and execute."

Heh heh, I have no comments on that.


Generally agreed, except: let's be careful with the notion of simplicity. I used the word "simplistic" which bears some negative flavor (pointlessly simple?). Lisp is relatively simple and yet powerful, i.e. it is not simplistic. C++ is incredibly complex (dare to write a full blown modern C++ compiler?) and powerful. Not surprisingly though, the simplicity of Lisp doesn't make it easier to grasp.

From this point of view, languages that are neither complex nor allow for complexity can be called "simplistic". They are easy to learn, easy to write code in, and as easy to grow to unmaintainable sizes because of their verbosity. Since we have very few readers here at the bottom of the thread, I will admit that every time I see all kinds of dancing around class instantiation, endless method calls etc in Java, where in some other language it would take a single function call, it reminds me of how kids count the steps out loud when they go up or down the stairs. When you grow older, you don't count any more, it's kind of implied :)

And I haven't found a better measure of quality of programming languages than that proposed by Paul Graham here: http://www.paulgraham.com/power.html

Edit: just noticed downvotes for my previous comment, so no, we are not alone :)


mojuba, I have to thank you for that link. I confess that I had never read that document prior to today. The thing that I like most about it is that he leaves it open ended.

He doesn't pretend to have all of the answers but rather invites the reader to embark on a thought exercise. Ignoring the question of comparing languages, that is an excellent example of how to write concerning this type of topic.

On comparing languages, I have to say that comparing languages based on power does make sense - with power defined as programmer productivity. From this perspective, I can understand your view on Java.

But is it the language itself that is to blame or the spaghetti code that all too often results from inexperienced users? I recall that the JRuby team has done some interesting things within the limitations of the Java language.

Note: To those who down-voted the original comment, I did not think that the down-voting is the most optimum solution for when you have a different perspective on an issue. Wouldn't it be better for everyone to chime into the discussion and increase everyone's knowledge with your perspective on the issue? This type of thing is why I have to ignore votes and just try to learn.


> I am not sure all the C folks are as productive as they could've been if they switched to C++. Same people.

I'm pretty sure that C folks are much more productive using C than C++. Hating the tools you are using tends to lower productivity to a halt.


The containers problem is the only one I find really annoying, and is more of a problem with the C standard library than the language. Using C with something like glib is a much nicer experience.


If you can't write your own linked lists or hash tables, you should not be programming in C. Glib is an abomination by people and for people that didn't understand C. Just like GNU is by people and for people that didn't understand UNIX.


ugh. you're using c? that's just an abomination for people that don't understand assembler.


The RAII benefits are definitely there and STL containers are pretty awesome, but you can still create generic containers in C by using void pointers. For example, a simple vector API:

  typedef struct { void *elements; int elem_size; int n; } Vector;

  Vector *vector_new(int elem_size);
  void vector_free(Vector *v);
  void vector_push(Vector *v, void *elem);
  void vector_pop(Vector *v);
  int vector_size(Vector *v);
  void *vector_at(Vector *v, int i);
etc. This is off the top of my head, but you get the idea. You can basically put anything you want in there as long as you say how large the elements are upon initialization.

There is a good book on generic C programming: http://sites.google.com/site/cinterfacesimplementations/


The problem with using void* pointers is that every access to an element costs one extra dereference operation. By using C++ templates, the compiler can create object code specifically compiled for each data type, without the need for pointers. (On the other hand, this can make C++ binaries much larger).


In this case, I'm not storing void pointers in the data structure, but I'm using the void pointer as a direct address into "elements". The memory layout is just a sequence of items of length elem_size. vector_push copies the item into that memory (and doubles the size of "elements" with realloc when necessary).


So you have a memcpy() call in vector_push? I wonder if that's less efficient than a straight-up assignment for small objects such as integers. The C++ equivalent can be further optimized during instruction generation by keeping things in the CPU registers as long as possible. In your C case, the int has to be written to memory before memcpy can load it into its buffer.


True, but that can be overcome by another function that just gives you an address to put a new item. You would say, for example:

  *(int *)vector_expand(v) = 2;


This is a super-unclean API, but that's just IMHO.

We'll just have to agree to disagree that what you've shown above is an acceptable API for a vector module.


I'm just making it up as I go along, it's not the prettiest thing. What would you do, in C?


highly opinionanted article. C++ breaks at places, where the compiler is instructed to not optimize (debug builds), and say operator overloading have been used for simple types, which creates function calls, rather than inlining it, while "C" approach (functon calls) would've worked not so slow. Talking from real experience, after coworker rolled heavy templated C++ math library for all consoles and PC, that worked very good in release, but debug builds crawled to 10 times slower.

The problem is that this library forced everyone to use it's types, interfaces, etc. - so the effect was spreading everywhere. Instead you should only do such things isolated, and provie "c" interface (for example zeromq does that).

Also do not propagate exceptions to client, especially if you are some middleware not used for the core of the things (for example social service api, advertisement api, or anything small used just as service).

Better do exceptions internally, and provide error codes or callbacks for client. Exceptions do not work on certain very popular gaming devices for examlple, and the user of your library might want to avoid them for other reasons

so do your best C++ in secret, if you want, provide us C interface


As usual, use the right tool for the job. Personally, I use C++ mostly, for different reasons:

- There are some very good cross-platform toolkits available for C++ (such as Qt).

- There is no C99 support in Visual Studio. At the same time, C++-98 works across all major compilers these days.

- STL containers.

However, C++ just is the best choice for the projects I am currently working on. For other projects, with fewer dependencies and no portability requirements beyond Unixy environments I prefer C.

Nearly any language can be superior, depending on the project. The linked article attempts to show that C++ is superior based on some specific situations where this may indeed be the case.


Interesting article. One major problem - it doesn't seem like the OP has ever actually used C for real world code. I say this as someone with a few years of experience with C (and a few years of C++).

None of the examples he showed of C code look like they were actually written by a C programmer. A lot of use of "goto"'s, for one thing. It looks like he tried reimplementing C++ in C.

Actually, that's exactly what he decided must be done: " If the C version wishes to match the C++ version in speed and memory usage, it will have to basically simulate the C++ implementation using a struct and functions which handle objects of that struct type (including things like initialization and destruction)."

So obviously, if you set out from the start with the assumption that to use a language, you have to reimplement another language in it, then of course you'll come to the conclusion that you should just use the other language. But that's not a conclusion that C programmers would be comfortable with.

By the way, as just one nitpick, I'd probably implement that Matrix with "void *" pointers, letting me substitute any struct I want in there later. Just my way of solving the "impossible to solve" problem he presents at the end.


If the author changed the title to "Why C++ is vastly superior to C for application programming", than i would agree for the examples he given in the article.


I agree with you, however most posts I have seen bashing C++ for its complexity do it from the perspective of the systems programmer as well. So it is nice to see someone showing how C++ can be superior.


This article should be "why C++ is vastly superior to C for multiplying and adding 3 matrices if you're not a very good C programmer".


So how would a very good C programmer implement this example? I don't think you can No True Scotsman your way around RAII and templates.


The "final straw" is easily overcome with unions.

Also I do not buy the argument that you do not have to follow coding conventions in C++ or that explicitly freeing memory is a bad thing. Also comparing the number of lines of code to determine the "best" language is childish. By that logic the language with the largest std. lib is the best.


Aside from obvious type safety arguments, you want to combine a 'long long' and a 'char' into a union, and for example have a byte matrix occupy 8GB of RAM instead of just 1GB?

If I were to defend C, I'd rather choose macros combined with plain typeless buffers. The choice between C and C++ in such cases is really a choice between the nightmare of wrong memory operations and total type unsafety on the one hand (C), and the nightmare of ineffective, bloated code on the other (C++). I believe the latter can be taken under control though.


C++ gets a bad wrap from people who have never seriously used it. I'm glad to see someone slapping back. It's a fine language that is very useful and will be for decades to come.


I don't think any language is vastly superior to any other in every case.

You can say that C++ is vastly more powerful (and flexible) than C, but for low-level/embedded/kernel etc development, many would argue that C is the superior language.

Many people would also argue that C++ is maybe too powerful and complex; you can do everything with it, but sometimes this makes it hard to decide how to do "anything" (procedural ? Object-oriented ? Using templates ?).

Lots of people (myself included) find it so complex that they only use a subset of it - "the good parts". However, agreeing which parts to use is often impossible.

I've written about about what I consider "the good parts" here:

- http://www.ppcsoft.com/blog/c-star.asp


Novice question: Why is C++ used for the vast majority of video games today? Why is it used for most commercial CFD codes? (A lot of codes in academia still use tons of legacy fortran though.)


I think this post sums it up pretty nicely: http://www.gamearchitect.net/Articles/WhyC++.html

Personally I think the advantages boil down to syntax and type-safety. For example, vector math is much more succinct and can be made type-safe. Constructors/destructors also can be handy for enforcing resource allocation.


yes, but you are not allowed to use exceptions, and the latter being major feature of the language puts one in strange situation.


Many people believe that C++ has useful features that improve the ability of the average programmer to write application programs. One problem is that different companies use different subsets. (The question of which language the Linux kernel should be written in is of limited interest.)

We could name a restricted subset of C++ as C+-. Many high quality and well-tested development tools for C+- already exist (the C++ tools). Now the problem remains of standardizing C+-. The most logical C+- variant to standardize on is the C++ subset used by the largest group of people, presumably the version defined by Google: http://google-styleguide.googlecode.com/svn/trunk/cppguide.x...

Now the question becomes is it easier for average programmers to build application programs using C or C+-? Using C+- or C? These are perhaps more useful questions than the long running C vs C++ debate.


"A few of lines of C++ code would need hundreds, if not even thousands of lines of C code, but an experienced C programmer is used to that."

Yea right. This guy is full of it. This article is very biased...


Of course it's biased. It's also not really wrong on a lot of counts. You really can write more expressive, terser code in C++, that sacrifices no readability and only a very tiny bit of performance (on non-embedded platforms). Seriously--RAII alone saves approximately twelve hojillion lines of code (and saves you from hideous factory-pattern libraries spread hither and yon, which is also a plus).

The flip side of that coin is that if you don't know what you're doing, you can blow off your leg, your friend's leg, and the legs of everyone in a twenty-foot radius.


Why C is vastly superior to C++:

  $ cat > foo.c
  #include <stdio.h>
  int main(int argc, char**argv){
    puts("hello world");
    return 0;
  }
  ^D
  $ cat > foo.cxx
  #include <iostream>
  int main(int argc, char**argv){
    std::cout << "hello world" << std::endl;
    return 0;
  }
  ^D
  $ time gcc -o hello-c foo.c
  
  real	0m0.039s
  user	0m0.020s
  sys	0m0.012s
  $ time g++ -o hello-c++ foo.cxx
  
  real	0m0.182s
  user	0m0.144s
  sys	0m0.028s


Great job measuring initialization time, now how about showing real world performance differences in actual large programs.


It is not about initialization time or even run-time performance, but about speed of compilation. When any non-trivial program in C++ takes minutes to build even on high end workstation all benefits that might come from it's "high level" features are moot.


Are you really saying that the time and energy you save coding and debugging by using high level features aren't worth a few minutes of compile time? It won't even be a few minutes except for the first time because of separate compilation.


That is exactly what I'm saying.

Compilation of C++ is really surprisingly slow. Mostly because compilation of modern C++ code involves parsing tens of megabytes of headers that mostly use complex to analyze constructs. Fact that C++'s grammar and semantics are incredibly complex does not help fast compilation either.

Separate compilation does not solve it much, because many simple changes, that affects only one file in other languages, force you to recompile significant subset of your codebase.

While you may save time coding I don't believe that debugging C++ code is in way easier than C code, I think it is quite the reverse. While you mostly eliminate some problems by using C++ you get whole lot of other C++ specific problems (static initializers, unexpected effects of overload resolution, unexpected effects of automatically generated code, weird performance characteristics...).

Most of this can be worked around, but in that cases you end up using subset of C++ that could be more flexibly implemented on top of C as few hundred lines of preprocessor macros and some coding conventions than by it's own compiler.


> Compilation of C++ is really surprisingly slow.

There's definitely something to what you're saying here. Or, rather, maybe something a few years ago. However, I don't think it really applies so much in 2011. Computers have gotten big and fast to the point where this argument is pretty meaningless.

Personally, I stopped caring about compilation time when I got a 3.6GHz i7 with eight in-flight threads. I'm OK with feeding the beast on this one--what I get from C++ is defnitely worth it. (Debugging isn't particularly difficult, I find - you end up using a subset of C++, but there's no way in hell you could implement my subset of C++ in C and not hate working with it.)


Concur. C++ compilation speed was legitimately a problem five years ago. Improved compilers, faster computers, and multi-core compilation have made it moot.

Often you'll see a C++ basher bring up compilation speed and then in the same thread advocate python + C as the happy medium, which I find crazy. C++ is so much higher level than C the need for scripting is often obviated. I've typically got about 2x SLOC expansion rewriting perl/python as C++, including stuff like headers, so really not much more code at all, just 100x faster and a tiny fraction the memory.

The other line you see, including elsewhere on this page right now, is that C and C++ are the right tool for the job in different domains. I really don't get this. C++ is straight-up a replacement for C. There is no C program that wouldn't be shorter and clearer rewritten as C++. The only occasion to not use C++ is when you don't have compiler support, which is extremely rarely a concern anymore. Even the lowest level embedded stuff is moving away from C in favor of C++.


Generally, people on Linux will be compiling using Makefiles, so just use make -j<num cores> to speed it up.


Using -j with C++ builds will always still be significantly slower than using -j with C builds.

Also, I believe the rule of thumb for the -j argument tends to be 2 times your number of cores. A surprising amount of build time is often spent on disk I/O, so you see worthwhile gains for quite a while running more jobs than cores.


GNU make also has -l (load limit) and make -j -l <number-of-cores> seems like better idea and in my experience works better. But still I tend to just run make -j without any limit which on modern systems works well enough.


Except when you use templates.


That's compilation time, not initialization time. Compiling C++ is tremendously slow compared to compiling C programs of equivalent complexity, and is a real issue even on modern hardware.


Also, using any stream buf in c++ is more "flexible" when compared to puts(), printf(), etc due to not having to define the type. Of course, you trade flexibility for performance.



a very good read.


My reason why C++ is vastly inferior to C:

It's just too goddamn easy to make a mess in C++ without noticing it. In C, if you make a mess, you will more likely notice it before it's unmanageable.


Can you be more specific?

I have a counter example (assuming I've understood you):

/* C /

int foo () { FILE x = fopen("bar"); return 0; }

/* C++ */ int foo () { ifstream in("bar"); return 0; }


C assumes that you know the contracts that calling a function implies. fopen()'s contract requires you to close the file after you are done with it.


I thought everyone knew this, because it creates more and better jobs[1]!

[1] http://harmful.cat-v.org/software/c++/I_did_it_for_you_all


You no doubt know that that "interview" was a complete fabrication. Please don't present it as fact.


is this an inflammatory troll submission?


No, I just see it taken for granted in most places that C++ was a mistake. The "general wisdom" is that C++ is too complicated for its own good and shouldn't be used for anything big (the C++ FQA is frequently cited). An article advocating the opposite position is nice.


Its Object oriented features !




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: