
Zed Shaw on C++ - mattrepl
http://librelist.com/browser//mongrel2/2010/7/15/c-verses-c++/#770d94bcfc6ddf1d8510199996b607dd
======
tptacek
I agree totally with Zed Shaw on this, but some quick observations:

* C++ circa 2000 (before mainline g++ could handle Alexandrescuisms) is significantly different from C++ circa 2010, albeit in ways that probably upset Shaw even more (the more central role boost has taken, the more "expressive" templates have gotten, don't call me on any of this stuff).

* C++ std::string is an abomination, but you can always just do what I've done and what lots of other C++ programmers whose code I've read have done: just use char* and a simple string library (or a custom string class).

* Ditto for stream IO, which is a huge C++ misfeature but which is also pretty much irrelevant (I know of no part of the standard C++ library outside of things that explicitly support stream I/O that rely on you using it).

* I don't get the POSIX argument at all; just call the POSIX functions, they work fine. Nobody mandates that you use (say) ACE_wrappers to do systems programming.

* const-correctness may be another misfeature (I know I make fun of it), but the point isn't hard to see: if you take the time to const-correct your code, the compiler will spit out errors that would have otherwise been runtime faults.

~~~
phaedrus
The problem with std::string is that when I type a quoted string in my code,
it isn't natively a std::string, it's natively a char* and gets converted to
strings. C++'s biggest mistake was not standardizing early on an official
object-oriented string datatype. It should have been in the first version of
C++, it should have been treated like a primitive type (even if it isn't), and
they should have said "thou shalt use this type for your strings". It makes me
sick every time I see some goofy custom string class.

One problem with const-correctness is C++ uses "const&" to mean two different
things: it could mean either a reference to a persistent object you're not
allowed to change, or it could refer to a temporary object which you're
prevented from changing because the changes will disappear. The problem is it
conflated _access control_ with _lifetime_. It would have been better if there
were a "temp" keyword - although the last thing C++ needs is more
combinatorics of type decorators.

On the subject of consts, though, C++ simply enforces const correctness more,
but doesn't the same criticism of confusing const apply to pointers in C as
well? You can just as easily declare a "const * const" in C as in C++. So I
fail to see why Zed Shaw writing something in C gets him away from that
"problem", unless he doesn't write const correct C.

~~~
stoney
The great thing about const is that if you don't like it you can pretty much
ignore it. The only time it might be necessary to deal with it is if you are
using a library that returns const objects.

If you do like const (which I do) then you can put it in pretty much
everywhere, except if you are dealing with a library that isn't "const
correct", but then a bit of type casting will save the day.

That's a big advantage of lots of the C++ features - if you don't like them
you can often just ignore them.

~~~
jimbokun
"If you do like const (which I do) then you can put it in pretty much
everywhere"

In retrospect, it might have been better to have a keyword for things that can
change. This goes equally for Java and "final". Making immutability the
default and mutability opt-in makes for fewer bugs and more reliable programs.

Arguably, this is what Clojure does where you have functional, immutable
constructs by default with ways to declare things that can change (refs,
etc.).

~~~
ramchip
const by default may not be a bad idea, but immutability of structures/objects
in C++ sounds like it would be a huge performance hit to me. I've used an
image processing library (CIMG) which lets you do things like `img = img1 * 2
+ img2 * 0.5`, instead of editing the image in-place. It's pretty, but with
regular 800x600 images the performance was around 2 orders of magnitude below
a simple for loop... it made a lot of extra copying and allocation instead of
mutating the image.

The thing is, this kind of code isn't an exception in the C++ world. C++ is
made for problems where performance matters: image processing, compilers,
browsers... immutability works for Clojure, but Clojure is a lot slower than
C++. It's more of an "enterprise software" language.

------
kqr2
There appear to be a lot of good rants _against_ C++. To name a few:

* Linus Torvalds : <http://lwn.net/Articles/249460/>

* C++ Frequently Questioned Answers : <http://yosefk.com/c++fqa/>

Are there any good passionate _pro_ C++ versus C arguments?

~~~
timr
_"There appear to be a lot of good rants against C++....Are there any good
passionate pro C++ versus C arguments?"_

By definition, the people who write the "entertaining" rants against C++ have
an axe to grind. The people who like C++ just silently _use it_ , and feel no
need to write advocacy blog posts for the language. Even if they were to blog
about it, it would be about as compelling as someone advocating for their
favorite brand of screwdriver. Like it or not, C++ is the incumbent, and it's
neither interesting nor fun to read someone advocating for the status quo.

Whenever you find yourself arriving at an opinion about a programming language
solely from rants that you read on some dude's blog, please keep in mind that
you're probably being most heavily influenced by the very people _least
qualified_ to teach you anything useful about the language. The internet is
filled with useful articles about C++, but you don't remember _those_. You
remember that Zed Shaw couldn't figure out how const works in C++, and once
wrote a funny email about it.

~~~
SkyMarshal
Good advice generally, but what axes do Zed and Linus have to grind? Sounds
like both just think C++ enables too much complexity to be worth the benefits.

~~~
zedshaw
It's actually possible to make C++ nice, the Grace library is wonderful. If I
ever have to C++ again I'm totally grabbing it and using it. The Grace value
types and type safe format operations are just the best thing ever.

My problem though is it's not the right tool for the job. Simply having access
to C level APIs doesn't instantly mean your language is awesome at making
servers and operating systems. Especially if that same language can't quite
figure out what the hell really happens on a copy, or during an exception, or
can't make decent strings and data buffers.

------
DanielBMarkham
I'm going to keep saying this until I turn blue in the face. Perhaps if I
stamp my feet it might get more attention (wink)

Please stop confusing the language with the APIs or the available libraries
and features of the language.

This sounds simple, but it's profound: simply because you _can_ do something,
that doesn't mean that you _have to_ do it that way.

To use Zed's example, let's say I'm hacking around a lot of strings. What's
wrong with rolling a string class, adding a member or two? You only have to
carry around a bunch of nonsense if you want to. If you don't want to use
templates and strings and such, don't use them.

This is another in a long line of articles that go something like this: We did
X in this certain way, and boy did it suck. Therefore all of X is the devil's
work and will destroy civilization.

You can put about anything you want in for X. It's like a (oddly enough)
template engine for writing blog entries.

You should go through stages in your career, with just about any X. Stage one
is that you are ignorant. Stage two is that you've tried it. Stage 3 is
expertise. Stage 4 is hate, and Stage 5 is grudging acknowledgement that parts
of X are okay for certain situations. You realize that yes, X is done poorly
maybe 99% of the time, but lots of smart people worked on it and there are
some little gems in there that are useful from time to time.

Looks like Zed is stuck on Stage 4

Throw away the templates, throw away all the library stuff you don't like --
is there a reason to make a class and wrap some things? If so, you can do that
in C++. You can't in C. It's a very simple question, and it has nothing to do
with any of the things Shaw is going on about.

~~~
jdminhbg
"What's wrong with rolling a string class, adding a member or two?"

The fact that it's 2010?

A language and its standard library are theoretically different things, but in
any practical sense, the choice to use a language carries with it the choice
to use its standard library. Additionally, the way the standard library is
usually reflects constraints placed on it by its language. Java, for example,
has a verbose and ceremonial standard library, and that's not a coincidence.

~~~
blub
The C++ standard library and std::string implicitly have specific constraints
and use cases, but they were imposed by the design process, not by the
language.

C++ has many string types because each string type has its strengths and
weaknesses. For instance, QString is a fully-featured and Unicode-aware string
written in C++ that I use most of the time.

std::string is good for most things. What are your specific issues with it?

~~~
jdminhbg
I don't write C++ and have no issue with std::string. I was taking general
issue with the OP's general issue with criticizing a std library alongside a
language.

------
phaedrus
I love C++, but I upvoted this because most C vs. C++ rants focus on things
that are not actually C++'s biggest problems. This is one of the few C++ rants
that actually brings up of legitimate points. They are not reasons that would
stop me personally from preferring C++ over C, but they are valid criticisms.

P.S. On the subject of format strings vs. cout and the "<<" madness, C++0x's
variadic templates will allow a type-safe printf. So hopefully in the future
we WILL see C++ move back toward format strings, but without loosing the type
safety. It also gives the possibility of instead of having to remember to use
%d for ints and %f for floats, we could just use format strings that use {1},
{2}, etc. as format string placeholders, the way C# does. Freeing you from
having to specify in the format string what the type is is something C++0x
type-safe-printf would allow you to do that you could never do in C.

~~~
zedshaw
Actually, this is what I loved about Grace. It was like all the crap that
pissed me off about C++'s design decisions just went away. It made C++ so nice
to work with.

------
watmough
Call me unlucky, but I've never worked at a company that had a _high
percentage_ of programmers (myself probably included) that could write solid
C++ using anything more than the absolute basics, i.e. basically a C subset.

I'd pretty much agree with Zed's rant, that C++ often isn't worth the bother,
_unless_ you have a project that specifically requires C++ features, _and_ you
have a development team that can actually write solid C++.

Maybe I'll call this Jonathan's axiom, but if your team doesn't have enough
experience to write in a Lisp-y (or any other genre such as ML-y) language,
you probably shouldn't be messing with C++ either.

Not many people that say they can write C++, actually can.

~~~
zedshaw
I think this is a key point, the language doesn't matter as much as the
capability and training the people using it have. This is why all these
language arguments are rather irritating, because I'll typically use what
works best. On some projects, C++ is great. On other projects C is best.
Python is great for some things too.

------
dtf
I don't get these rants. Both C and C++ are such barebone languages that you
can take or leave pretty much everything but the common syntax. Zed decides
C's string functions are not up to scratch, and so uses bstring. Plenty feel
the same about std::string, and will use bstring's CBString, Qt's QString, or
some other class in their C++ code. Exceptions? Take them or leave them.
setjmp/longjmp? Take them or leave them. Templates? Take them or leave them.
Macros? Take them or leave them.

~~~
loup-vaillant
The problem is, your co-workers will do the same with other features. Unless
the project is under a strong dictatorship, you'll end up taking everything.

------
fauigerzigerk
I agree with most of what he says but not with his memory management argument.
In C++ you could do something like this:

    
    
      f() {
        LinkedList list;
        populate(list);
        use(list);
        //forget
      }
    

Freeing the list elements is done in one place only, in the destructor of
LinkedList. In C, you have to call some kind of free function in every single
place a LinkedList is used. The burden of managing memory is on the user of a
library, not on its creator. I don't think this is enough to justify using C++
though.

~~~
yonilevy
Thank you for bringing that up. It's called RAII and it's one of my favorite
features of C++. The fun thing about it is that it can also be used to manage
other resources such as files, sockets, locks or what not.

------
Terry_B
I really dislike C++ but more to the point I really dislike other people's
C++.

This is triple compounded when you only have to do C++ occasionally. I've
never even got close to the point of looking at something like const *const
char & and reading it like it was something normal like others seem to do.

~~~
mhd
_I really dislike C++ but more to the point I really dislike other people's
C++._

That's right on the money. I can find a subset of C++ that I like and that I
could program with, but that assumes that I'm not collaborating with someone
and that I don't have to use C++ libraries (It's not just the code, it's the
APIs, too). The latter is almost worse. I could imagine a company that has
some rather strict standards, where the C++ development environment doesn't
suck completely. Google's style guide seems to indicate that they might be one
of those companies [1]. Much more likely you'd have to work with something
like MFC, VLC or the complete boost hodgepodge.

And Zed is right when he's talking about the template meta-programming fad. I
haven't seen any project where the pros outweighed the cons. And yes, I've
read Alexandrescu.

People often say that you need all those features to build large applications.
Which reminds me a lot of the "Doctor, it hurts when I do like this!" joke…

[1]: [http://google-
styleguide.googlecode.com/svn/trunk/cppguide.x...](http://google-
styleguide.googlecode.com/svn/trunk/cppguide.xml)

~~~
danieldk
There are some very good template-based libraries. I think STL is mostly ok,
but also libraries like Eigen are great, and avoid a lot of code duplication
through templates.

<http://eigen.tuxfamily.org/index.php?title=Main_Page>

~~~
mhd
Templates as they were used/implemented in earlier days where quite okay,
apart from having to use other people's libraries, I preferred to solve
problems using generic programming than just building class hierarchies (which
now nicely translates to functional programming).

Apart from very crappy compiler support (looking at you, Microsoft) I really
liked the STL. It's simple enough (maybe a bit too simplistic).

Template meta-programming is a whole 'nother deal. It's like the rabid
daughter of an unhappy marriage between Lisp's macros and Perl. From some
angles, she looks rather enticing. Then she bites down on your crotch.

------
alecco
Exceptionally good critique. But there are exceptions: programming for
Google's V8 in C++ is a pleasure. I've never seen any interpreter code so
clean and easy to extend. Like a breath of fresh air.

~~~
zedshaw
Embed V8 into Python, then tell me how great C++ is.

In other words, C++ is great until something else has to call it. Then you're
hosed and end up wrapping everything in C anyway.

~~~
phaedrus
That's what I've written a library to fix - it makes it quick and easy to bind
C++ api's to make them callable from a dynamic language. Not only can you bind
a C++ function with 1 line of code, but if that function returns an object,
the returned object's member functions are callable on its scripted instance:

<http://github.com/dennisferron/LikeMagic>

Currently there is only an Io backend, but the library is designed so that the
same C++ bindings can be used with multiple different backend languages. It's
like Boost::Python on steroids.

~~~
SAHChandler
I've seen you talk about this on the Io list for a while now, but you never
seemed to have posted a link to it. Glad I can finally take a look at it :)

------
afhof
What would be better is if C and C++ divorced each other and people realized
that they are two separate languages. All of Google's results for C questions
end up linking to some "C/C++" forum, which is almost certainly not what I'm
looking for. I'm sure the other way 'round is true too.

------
felideon
_"If I wanted to fry my brain trying to figure out how to add two numbers with
templates I'd go use LISP."_

Probably just a tongue in cheek comment, but I wonder what he meant.

~~~
mahmud
Probably another run-of-the-mill confusion of macros for templates.

"LISP" is a convenient red-herring to throw into PL diatribes; it shows the
speaker has some authority since he is "aware" of Lisp, and the glowing and
mystical connotations that this, vague, awareness carries.

~~~
zedshaw
No, more a nod to Lisp getting "metaprogramming" right when C++ screwed them
up. If I've gotta do it, I'd rather do it in a language where the turing
completeness wasn't designed to be a tarpit.

~~~
mahmud
And there goes my attempt to trick you into becoming a Lisper :-(

Learn CL inside and out, not because you want to be a better programmer, but
penning "Lisp is a Ghetto", if you get it right, will guarantee your name
echoes in the hallways of hacker heaven long after we're both gone.

------
mark_l_watson
I have to agree with the spirit of the article. In the late 80s and early 90s,
much of my work was in C++, and I did some mentoring, wrote a bunch of C++
books, etc.

After my C++ _period_ , I did a major project for myself and just used C -
like a breath of fresh air after C++

In all my years using C++, I think that the only good applications where C++
made sense was in Nintendo and PC game development at Angel Studios and some
VR development for Disney and SAIC. Everything else that I did in C++ should
have been done in different languages.

------
shin_lao
The std::string example given by Zed shows that he didn't hack around C++/STL
much.

There is a whole entry in Exceptional C++ Style (or another Herb's book) that
says how much std::string sucks and how you can write an equivalent extremely
quickly.

Anyway, don't like std::string ? You can use std::vector in place very easily,
that's a well known trick (thanks to the guarantee that &v[0] returns a
pointer to the data if v is a vector).

He talks about references but he seems to ignore the capability of C++ to
offer perfect forwarding which enables you to greatly increase performance and
memory usage and that's very difficult to mimic in pure C.

There's a lot to write about inaccuracies in this post actually, but what the
point? People who hate C++ will discard them and people who love it already
know it.

I tire of reading posts from people who didn't like a language for whatever
reason and try to rationalize it.

------
prog
This is the first time I heard of Grace C++[1]. Looks very useful. I was
looking for string that can be used for binary data. Looks like they support
that too.

[1] <http://grace.openpanel.com/>

~~~
zedshaw
Grace is absolutely awesome. The value type and format syntax are exactly the
way it should be done.

------
drawkbox
I like C or C++ for native but use C++ more because I write it with
simplicity. Complex C++ like MFC, Windows API, template hell is disgusting and
wrongly gave C++ a bad name.

C++ OO can be done to really abstract the application but still be very
manageable and simple. Also C++ is a game industry cornerstone. I think game
code in C is actually harder to consume that game code in C++.

------
ehnus
I always see streams brought up as a critique of C++, at least compared to how
it is handled by C, and I agree that they are terrible. However, everyone else
also agrees that they are terrible, and as an added bonus the C IO functions
are still available.

C++ brings a lot of heavy-weight machinery to the table but the best part is
that you don't have to use it. If you just want to write C but desire
templates to reduce the amount of writing you need to do then so be it, write
C-with-templates!

My big beef with the language is mostly due to the legacy crud it is saddled
with in the C preprocessor. Many of the build time issues I find myself
suffering with are because of people, for example, including Windows.h a) in
the first place and b) not defining WIN32_LEAN_AND_MEAN. Junior (and senior,
for that matter!) developers seldom know how to properly structure their code
so that their iteration times don't plummet.

------
mattrepl
Pretty good rip on a few annoyances of C++ in Zed's fantastic ranting style.

~~~
lanstein
Classic Zed. Nice, haven't heard from him in awhile.

------
zaphar
I really do love a good C++ rant.

~~~
mcantor
Thank you for this post. For the life of me I cannot explain why, but it
delighted me immensely, and I am inexplicably incapable of reading it in my
head without an exaggerated British accent.

~~~
zaphar
Strangely enough, despite being thoroughly american, I am given to british
spellings and mannerisms in my writing and speech. I think it has something to
do with being really into british humor and fiction for most of my life.
(british comedies, Terry Pratchett, Dr. Who...)

I constantly get teased by friends about my british spelling s of common
words.

------
obiefernandez
Doesn't the D language fix a lot of the issues that Zed is complaining about?
Constantly surprised that it's not more mainstream...

~~~
zokier
D could have saved us from the horrors of C++, but it dropped the ball.

<http://www.jfbillingsley.com/blog/?p=53>

<http://news.ycombinator.com/item?id=911858>

------
malkia
The problem with const string& is that the resulting string is not interned -
e.g. one copy in memory, which would later allow to save memory, compare by
pointer equality (eq), etc.

I understand that the language cannot express it, and that's why other
languages (such as lua) do it the right way - immutable strings all the way,
or at least by default (NSString)

~~~
dzorz
You can make a string class that interns strings. Language can express it, but
std::string doesn't do it.

------
tzs
That was rather bogus. Sure, destructors are horribly complex in their
interaction with all of the other horribly complex C++ features. But unless
I'm reading it wrong, Aughey wasn't suggesting using all those other features.

If you have some reasonable self-control, it is quite reasonable to use C++ as
a small superset of C.

------
malkia
There are great C++ projects, but the big compile/link times they have are not
a small deal. Also the compiled libraries take a lot of space. Examples:

Qt, wxWidgets, LLVM, boost

Hopefully we have IncrediBuild at work, and we don't have to deal all the time
with such huge frameworks.

~~~
nickelplate
You don't have to build these libraries from scratch every time. You could
store pre-compiled binaries in a shared drive for every possible
configuration, and developers can simply copy them to their machine. Not that
big a deal.

------
dan00
Just using constructors/destructors and class encapsulation makes code so much
more readable.

And most exception problems are solved with RAII. If you're using RAII, then
you won't have memory leaks when exceptions arise.

------
boryas
I'd like to extend his position to the argument that the semantics of any
language that isn't ML or Lisp are too complicated...

------
rcfox
Forgive me if this is a terrible question, but who is Zed Shaw, and why should
I care about what he says about C++?

~~~
fauigerzigerk
He is a guy who has written some great code (Mongrel) that is valued for being
clean, correct and fast.

------
JabavuAdams
The problem with a lot of these posts on HN is that the audience seems to be
rather biased towards low-performance app areas like web, and business apps.

Oh noes! I have to handle 10 requests a second!

Take a look at the SWENG-gamedev mailing list for some of the performance
issues that people face in games and game tools.

/pissing-contest

Note: obviously this is not an argument _against C_ instead of C++. It's more
to forestall the meta-discussion.

------
BonoboBoner
I hoped it would be a blog post like "C++ is a ghetto"...

------
mkramlich
I've seen this pattern a lot when it comes to the order of learning/mastering
languages: C, then C++, then back to C

~~~
16s
After getting use to the STL containers... I could never go back to pure C. I
use C++ daily and love it. Nothing against C (if that's what you like) it's a
great little language.

Why is it that C programmers bitch about C++, but C++ programmers don't bitch
about C?

~~~
phaedrus
Because we're having too much fun writing cool things in C++ to bother to
write rants.

~~~
torpor
Because you're too busy waiting for all that C++ code to compile before you
can be too busy debugging it ..

FtFT! :)

------
c00p3r
The portable subset of C++ were around long before mozilla, webkit or
chromium. Anyone can read mozilla's or google's guidelines about which subset
of c++ is safe to use.

One of the best examples is Informix RDBMS which was acquired by IBM in 2000.
And the second best is... JVM. ^_^

------
c00p3r
Bunch of age-old banalities from a famous narcissist on top of front page.. Is
there any HN 2.0?

~~~
zedshaw
2.0? You really trotted out that cliche? Ok, I'll one-up you:

2005 called, they want their joke back.

~~~
c00p3r
Thank you for your reply! We all know you're very productive writer. ^_^

------
d0m
The real problem with C++ is that there isn't a fucking split function in the
standard library.

~~~
dan00
I donate you one:

    
    
       #include <vector>
       #include <string>
       #include <iostream>
    
       typedef std::vector<std::string> Strings_t;
       Strings_t split(const std::string& string, char onChar)
       {
          Strings_t splitted;
          size_t lastSplit = 0;
          for (size_t i = 0; i < string.size(); ++i) {
    	 if (string[i] == onChar) {
    	    if (lastSplit != i)
    	       splitted.push_back(std::string(string, lastSplit, i - lastSplit));
    
    	    lastSplit = i + 1;
    	 }
          }
    
          if (lastSplit != string.size())
    	 splitted.push_back(std::string(string, lastSplit, string.size() - lastSplit));
    
          return splitted;
       }
    
       int main() 
       {
          Strings_t strs = split("$$qqqq$$$w$$$eee$$a$d$$$$$", '$');
          for (Strings_t::const_iterator s = strs.begin(); s != strs.end(); ++s)
    	 std::cout << *s << "\n";
    
          return 0;
       }

~~~
d0m
I never said I didn't know where to get one, or to actually write it. In fact,
you can do it way simply with getline(). It just always pissed me off when I
hack a little something and there is no split.. I then need to either include
boost which is huuuuge compared to my 200 lines file.. code it myself, get a
snippet from internet.

The point is: in C++, there are so much things.. It's like a fuckload of
thousand of features to satisfy everyone. How the fuck can there be no split?
Ruby, split, python, split, java, split, php, split, C# split, C++
-your-20-lines-function-which-only-support-splitting-on-a-char-but-not-on-a-
string.

~~~
dan00
Well, all these languages are very stringy because they are very weby.

------
blantonl
Zed is literally the Kimbo Slice of the technical community.

~~~
WilliamLP
Wow, an MMA analogy on this site? Who are Seth Petruzelli, Roy Nelson, and
Matt Mitrione then?

~~~
charlie_root
Donald Knuth is Hélio Gracie

Edsger Dijkstra is Masahiko Kimura

John McCarthy is Yip Man

Paul Graham is Bruce Lee

Steve Jobs is Fedor Emelianenko

Linus Torvalds is Mauricio Rua

Bill Gates is Brock Lesnar

Steve Ballmer is Eric Esch

David Heinemeier Hansson is Anderson Silva

Guido van Rossum is B.J. Penn

Sergey Brin is Antônio Rogério Nogueira

Lawrence Page is Antônio Rodrigo Nogueira

~~~
WilliamLP
That's awesome! I laughed a lot at Steve "Butterbean" Ballmer and the Google
brothers! I thought John McCarthy was going to be John McCarthy.

Yukihiro Matsumoto -> Kazushi Sakuraba

Dennis Ritchie, Ken Thompson, Rob Pike -> Royce, Rickson, Renzo Gracie

Joel Spolsky -> Tank Abbot

Bjarne Stroustrup -> Matt Hughes

RM Stallman -> Ken Shamrock

Steve Wozniak -> Mark Coleman

Rasmus Lerdorf -> Jon Fitch

Don Stewart -> Art Jimmerson

------
travisjeffery
"They'd have been better off to just invent a new keyword:
doesnotfuckingchange and stop there."

And now I have tea to clean off of my monitor and keyboard.

