
Popular Myths about C++, Part 1 - jabaldonedo
http://isocpp.org/blog/2014/12/myths-1
======
mike-cardwell
"Finally, which version is likely to be the most efficient? Yes, the C++
version, because it does not have to count the argument characters and does
not use the free store (dynamic memory) for short argument strings."

I just compiled the C code and the C++ code using:

    
    
      gcc -std=c99   -Wall -Wextra test.c   -o test
      g++ -std=c++11 -Wall -Wextra test.cpp -o test
    

According to valgrind:

    
    
      C:   total heap usage: 1 allocs, 1 frees, 21 bytes allocated
      C++: total heap usage: 4 allocs, 4 frees, 145 bytes allocated
    

Using gcc (Debian 4.7.2-5)

[edit] Repeated using gcc 4.9.1 and clang 3.5.0 with -std=c++14. No
difference.

[edit] Seems with Clang and libc++ it's better than the C implementation as it
doesn't do any heap allocation:

    
    
      clang++ -stdlib=libc++ -std=c++14 -Wall -Wextra -g test.cpp -o test
      total heap usage: 0 allocs, 0 frees, 0 bytes allocated
    

But still, that's only because the C version was explicitly written to use
heap allocation. It need not do so.

~~~
pierrebai
This is the archetypal problem with benchmarks: not only are they hard to
design, but people will incorrectly nit-pick the results.

You count the number of allocations, without looking at the big picture: this
is a toy example. It provides the hard-coded input to the function. This
results in the C version not having to allocate memory for the hard-coded
literals and the function problably being inlined and optimized away and the
strlen() calls being equally optimized away as the length of the strings are
known at compile time.

In the real world, these would come from some input where they would need to
be allocated on the heap, just like the C++ version does. It would use just as
many allocations, except they will all be hand-rolled, hand-held, error-prone,
with every bit of memory management explicit. C++ is superior in every measure
here. Only in toy programs and hard-coded strings does C wins.

If the goal was to have as few allocations from hard-coded strings, then just
write "foo@bar" and avoid the concatenation altogether. That is not the point
of the example.

(Also, the newer C++ standard support std::string literals, FWIW.)

~~~
StephanTLavavej
C++14's "meow"s is syntactic sugar for string("meow"), with identical
efficiency.

~~~
mike-cardwell
If that's the case, then when I do:

    
    
      auto str = "something";
    

Why is "str" a "const char _" rather than a std::string? Tested using
"-std=c++14" with both gcc version 4.9.1, clang 3.5.0 and with both libstdc++
and libc++ ?

[edit] If you're the guy who does the MSDN videos on C++, _thank you*. They've
been incredibly useful to me.

~~~
StephanTLavavej
Sorry, wasn't checking my HN comments frequently (unlike Reddit there's no
little red icon).

"meow" is a traditional string literal, whose type is const char [5] (array of
5 const chars). When you say "auto", you get the same deduction as when you
pass something to a template foo(T t) taking by value. This triggers "decay",
where arrays decay to pointers. Hence auto (and T) is const char *.

"meow"s is a user-defined literal (the Standard Library is a user as far as
the compiler is concerned), for which you must include <string> and say "using
namespace std::string_literals;" or something equivalent. The specification
for UDLs says that this calls operator""s() which returns a std::string by
value.

Yep, I'm the video guy. Glad you like them!

------
Ragnarork
I'm looking forward for the next part, as the last three myths are the ones
I'm waiting for their answers, as they should be pretty interesting.

C++ has come a long way, and I really feel C++ 11 could very well replace Java
as a learning language for computer science students (I don't think it'd be a
good choice for an introduction to programming for non CS students), and I see
many benefits in this, the biggests being IMHO C++ NOT being fully object-
oriented, and the possibility to do either low- or high-level stuff, depending
on what you're teaching.

~~~
wmt
My biggest issue with most garbage collection implementations is the lack of
RAII. While I love the ease of reading and writing Python or Lua, I'd love to
be able to create a local object, like an open file or a database connection,
and have it destructed immediately on return.

~~~
idbfs
I'm not sure about Lua, but for Python it sounds like you may be interested in
the "with" statement.

------
Symmetry
What sort of C programmer wouldn't use snprintf to do the formatting? If the
C++ program can use std::string then it's only fair to let the C program
import <stdio.h>. And honestly printf is so much nicer to use than iostreams
I've always considered the relative ease of putting together a formated string
one of C's strengths relative to C++.

~~~
linuxlizard
What sort of C programmer wouldn't test for malloc() failing.

Drives me batty to see articles where malloc() is happily assumed to always
succeed.

~~~
ExpiredLink
> _Drives me batty to see articles where malloc() is happily assumed to always
> succeed._

... as in Linux.

~~~
mikeash
Malloc will never fail on Linux _due to running out of RAM_. However, it will
fail for other reasons, such as running out of address space. You can easily
run out of address space in 32-bit processes, since you only have 4GB of
address space, or less. It's much harder in 64-bit processes, but since you
can allocate vast chunks of memory without having them be backed by RAM, you
can accomplish it there as well.

~~~
antimagic
It's not so much that malloc can fail, but that you're likely to get whacked
by OOM before you run out of address space on linux. To get malloc to return a
NULL, you would have to be allocating more than 4Gb of memory on a 32 bit
system, the system has to have no swap, and you have to not have used any of
the memory between the last physically available memory, and the memory
allocated by the chunk that takes you over the 4Gb limit. Anything else gets
you SIGKILLed.

~~~
mikeash
Swap has nothing to do with it. Getting malloc to fail is easy:

    
    
        malloc(-1);
    

With address space fragmentation, the requested size can be a lot smaller and
still fail. With overcommit, you can allocate a ton of memory without using up
any RAM.

------
robert_tweed
Myth 6: off-by-one errors are prevalent, even in _articles_ about C++.

PS: Since HN is specially humour-impaired, and for the DNRTFA crowd: this is a
complaint about the article's formatting.

------
drblast
I like C++, but using it to teach beginners who have no knowledge of C or
compilers in general is a horrible idea. My college CS101 course was taught
using C++, and I was lucky because I already knew multiple programming
languages before that.

1\. There are a lot of abstractions in C++ that make it very powerful, but the
reason those exist would be completely lost on a newbie. Pass-by-reference vs.
pass-by-value? Oh yeah, there are pointers too that you might run into, that's
almost exactly like a reference but with a different syntax. We have smart
pointers instead to obscure that from you, but if you search for examples
online you might run into any of these. But don't worry about all of this;
these language features only exist because of type safety and performance
which you have no clue about. Just change the syntax until it compiles and
runs.

2\. Programming is more than write->compile. Debugging is as important, if not
more, and heaven help you if you're a beginner trying to debug C++. With C
you'll at least get exposure to machine code that pretty much looks like the
program you wrote.

3\. C++11 is an improvement, but it's not ubiquitous and it adds abstraction
that someone without a solid C/Assembly background will have very little
chance of understanding.

Teaching C++ to someone with a firm grasp of C would be a lot easier and
additive. "Here are the new features that can help the compiler make your
program more performant or type-safe or fix your memory leaks." Otherwise
you're throwing a bunch of solutions at students to problems they've never
had.

~~~
cheez
It is the end of 2014 and I am using C++11 on Windows, OSX and Linux without
too many incompatibilities. Of course, you need the latest versions of the
compilers but it's ubiquitous enough.

------
pherocity_
I'm getting so tired of the word myth and how it's used so incorrectly. These
may be misconceptions, but they are not myths. In truth, some of these are
factually accurate and you're framing them as a misconception to drive a
narrative. I can't help but consider that link-bait, even though structured
differently, this would be a good article.

~~~
Iftheshoefits
First, which of the "myths" are "factually accurate" and in what sense?

Second, I don't find his use of "myth" objectionable, in much the same way I
(as a scientist) don't find objectionable the use of "theory" to mean "guess"
in non-scientific speech (attempting to impose "guess" as a meaning when
discussing scientific theories is anathema). This use of "myth" here is fairly
common, at least colloquially in America, as a rhetorical flourish in place of
"misconception."

------
WhitneyLand
Does anyone choose C++ anymore unless it is required by
environment/legacy/performance constraints?

Back in the day I read Bjarne's book cover to cover, used C++ for very large
scale projects, and was one of those guys who could make sense of arbitrarily
complex pointer expressions.

Now I mostly regret it. Led down the rabbit hold of multiple inheritance, STL
being much more complicated than templating in other languages, and watching
devs take years to master all of the subtleties.

He alludes (next article) to garbage collection not being more reliable than
manually memory management? Yes GC has it's own disadvantages and there are
many ways in C++ to mitigate memory management problems, but seriously I wish
I had a dollar for every hour of time spent on a memory allocation bug in C++.

~~~
Scea91
With the recent updates to the standard C++ is actually a really pleasant
language to use. You just have to know a lot, but the reward is there.

~~~
jbergens
Yes, but it seems the whole team (or all teams in large enterprise projects)
must know a lot. Otherwise you still and up with a lot of hard to read, unsafe
code. If you start with a very large codebase of old C/C++ you might have to
rewrite large parts of it to reap the benefits and in that case you might want
to look into other languages as alternatives. I agree that for a green field
project with very good developers C++ 14 looks nice.

~~~
Scea91
I agree 100%.

------
0942v8653
Not showing up. Here's an archived version:
[https://archive.today/LoOe1](https://archive.today/LoOe1)

~~~
gamesbrainiac
Thanks. Very short post though. What I have to say is, that C++11 and onwards
had indeed made C++ much more approachable. I think Herb Sutter's talk on
modern C++ is also worth a look. [0]

[0]
[https://www.youtube.com/watch?v=TJHgp1ugKGM](https://www.youtube.com/watch?v=TJHgp1ugKGM)

~~~
rumdz
I just finished watching this and 48:58 really blew my mind.

~~~
Scea91
I've written an article about this:
[http://blog.honzabrabec.cz/2014/07/06/the-power-of-
algorithm...](http://blog.honzabrabec.cz/2014/07/06/the-power-of-algorithm/)

------
ExpiredLink
Good luck trying to understand C++ without C. The numerous C++ traps and
pitfalls will just look mad to you. BTW, 'multi-paradigm' is an oxymoron. Not
even Scala uses that concept any more.

~~~
stinos
_Good luck trying to understand C++ without C_

look at it this way: suppose some alternate universe where there is no such
thing as C, it just doesn't exist, nobody ever heard of it. Why would you not
be able to completely master C++ that universe? The traps and pitfalls which
you consider C, would then just be known as C++ (just as in reality they are
C++ now, maybe not just always named as such). I think that's one thing what's
being advocated here.

Anyway, what traps do you have in mind specifically?

~~~
millstone
Much of C++ can only be understood in the context of C. For example, why are
string literals not std::string, and what the heck are null-terminated strings
about? In your alternate universe, C++ would be a nonsense language full of
absurd design decisions. Understanding C is perhaps necessary to understand
why C++ works the way it does.

~~~
bkeroack
Even further, why are strings considered a linear sequence of 8-bit characters
(defaulting to ASCII)? That's madness in 2014! If I give you a sequence of
bytes and tell you it's a "string", that's no more meaningful than if I gave
you a bunch of bytes and said "this is music" or "this is a picture". Without
telling you the encoding you have to blindly guess how to interpret it.

Go does a good job of rectifying this: strings are generally opaque binary
objects--indexing into them gives you abstract "runes" (representing Unicode
code points) which can then be encoded into various flavors of UTF characters.

~~~
jerf
"Go does a good job of rectifying this: strings are generally opaque binary
objects--indexing into them gives you abstract "runes" (representing Unicode
code points) which can then be encoded into various flavors of UTF
characters."

Overselling Go a _bit_ there. Indexing into a string gives you that byte:
[http://play.golang.org/p/rxeexRzW7e](http://play.golang.org/p/rxeexRzW7e)

There are ways of iterating along a string by "rune" but it's not the default.
That said, given that strings in Go are assumed to be UTF-8, indexing into
them by rune is expensive and if you actually want to iterate by Unicode char
I'm not bothered by having to be a bit more explicit about it.

~~~
bkeroack
Strictly speaking, indexing into a string gives you an integer type (as your
example also shows):
[https://play.golang.org/p/i7_MKja_mQ](https://play.golang.org/p/i7_MKja_mQ)

"Rune" is an alias for int32. So we are saying the same thing, essentially.

~~~
jerf
Try that with something that _isn 't_ one byte in UTF-8. It won't work. We
aren't saying the same thing.

~~~
bkeroack
OK.
[https://play.golang.org/p/Q94GFI02ru](https://play.golang.org/p/Q94GFI02ru)

I'm not sure what your point is in this argument? You're saying the above is
worse than braindead C ASCII-only strings?

~~~
jerf
That promising that "Go strings allow you to index into them to retrieve
runes" is overselling Go's string support, of course. That's why I led with
that statement, since it is what I was trying to say.

It's best to be correct about how languages work, because when you interest
someone in a language via a false statement, they do not end up thinking
highly of either you or the language when they discover the falsity. While I'm
not sure I'd call myself a Go "advocate", I do prefer that people like and/or
dislike it for valid reasons rather than invalid ones.

------
divs1210
Has Linus read this yet? I can hear him screaming in fury. :D

~~~
pjmlp
Linus has ported his Subsurface project to Qt, thanks to the current state of
affairs in Gtk, so I imagine he might be a bit more welcoming to C++ nowadays.

~~~
throwawayaway
[https://github.com/torvalds/subsurface](https://github.com/torvalds/subsurface)

pretty interesting! the .c's heavily outnumber the .cpp's.

there's nothing like having your prejudices confirmed to harden them, so I
question whether he is more welcoming.

~~~
towelguy
There's a video about it
[https://www.youtube.com/watch?v=ON0A1dsQOV0](https://www.youtube.com/watch?v=ON0A1dsQOV0)

Apparently, Qt takes away most of the problems they have with C++

~~~
throwawayaway
So the guy who took over from Linus doesn't mind Qt. The guy reiterates how
much Linus does not like C++. I want my 12 minutes back!

------
mikeash
A major problem with C++ is a lack of consistency, which you run into if you
start trying to generalize the ideas presented in this article.

The article demonstrates string concatenation using +. That is great! Except
it's inconsistent. The article's example works fine, of course:

    
    
        return name+'@'+domain;
    

I'll skip over the weird use of '' instead of "". Now let's say I want to
prepend mailto: as well:

    
    
        return "mailto:" + return name+'@'+domain;
    

So far so good. But I think it might be clearer if the colon was separated
out:

    
    
        return "mailto" + ":" + name+'@'+domain;
    

Oops, this no longer compiles. Hey beginner programmers, let's take time out
from the arduous task of learning basic programming to understand what a const
char * is and how it differs from const string and why you can + two strings
or a string and a const char * or a const char * and a string but you can't +
two const char *s.

The next example demonstrates initializing a vector:

    
    
        vector<int> v = {1,2,3,5,8,13};
    

This is great, of course. The example after that introduces "auto" so you
don't have to write the type of a variable. Well heck, let's combine the two!

    
    
        auto v = {1,2,3,5,8,13};
    

Kaboom. Oops. You can use auto, or you can use {} to make a vector, but you
can't do both at the same time! OK, beginners, let's take some more time out
from learning what you came for and instead learn about the complex machinery
that handles initializing a custom type with {} and why "a = b" can do
arbitrarily complex things depending on the types of a and b.

I had a job in college tutoring students in my CS department's first-semester
programming course, which was taught in C++. People would routinely come in
with code that wouldn't compile because of some tiny mistake, but which
produced literally pages of error output. There was no way for new students
who were still struggling with the concept of a loop to figure out what they
were doing wrong, besides finding somebody who had already been through it.

This was a long time ago, and C++ has improved, especially in the error
message department. But these problems are still there, even if somewhat
diminished, and other languages don't have them.

The fundamental problem with C++ is that it grew organically from humble
beginnings without any apparent plan. This allowed to adopt a lot of nifty
features and become extremely powerful, but it also means that there are a ton
of bizarre corner cases and inconsistencies to deal with. For many projects,
the tradeoff is worthwhile. But it's one of the worst choices imaginable for
teaching new people to program.

~~~
jlarocco
> auto v = {1,2,3,5,8,13};

> Kaboom. Oops. You can use auto, or you can use {} to make a vector, but you
> can't do both at the same time!

IMO it would be more confusing if that created a vector<int>. Unless the
compiler is reading your mind, how is it supposed to know you meant a
vector<int>, a set<int>, deque<int>, a struct { int a,b,c,d,e,f}, or some
other object who's constructor can take 6 ints?

~~~
mikeash
The way most other languages handle it is that the list literal construct just
creates a list, and if you want something else then you need to explicitly
convert. For example, in Python:

    
    
        x = [1, 2, 3, 5, 8, 13] # this is a list of integers
        y = set([1, 2, 3, 5, 8, 13]) # this is a set of integers
    

There's nothing inherently wrong with C++'s initializer list approach. Nor is
there anything inherently wrong with auto. But they collide in unfortunate
ways because they haven't been designed such that they go well together. C++
is full of things like this. Responding with "well, that makes the most sense"
for any given feature is missing the point entirely.

~~~
jlarocco
> The way most other languages handle it is that the list literal construct
> just creates a list, and if you want something else then you need to
> explicitly convert. > For example, in Python:

> x = [1, 2, 3, 5, 8, 13] # this is a list of integers

> y = set([1, 2, 3, 5, 8, 13]) # this is a set of integers

Actually, that's not the best way to do it:

    
    
        y = {1, 2, 3, 5, 8, 13} # this is a set of integers without creating a list first.
        z = set(1, 2, 3, 5, 8, 13) # so is this
    
    

In C++ {} is syntactic sugar for "Create an initializer_list with these
values," which is what happens when it's assigned to an "auto" variable. Not
surprising at all. If you want a different type, you need to specify the type
that you want.

Maybe it's confusing to beginners and people who don't take the time to learn
the language, but C++ isn't catering to those people.

Don't get me wrong, there are a lot of "gotchas" in C++, I just don't think
the two you've posted are very bad.

~~~
mikeash
Um, the whole point of this discussion is about the claim that C++ is a good
language for beginners to learn.

I have problems with using C++ to build real projects with experienced
programmers too, but those are mostly different problems.

------
netheril96
The list initialization syntax touted by Bjarne Stroustrup himself as beginner
friendly is not even friendly to advanced users. Tell me how to debug or teach
students the difference between

    
    
        std::vector<int>{10}
        std::vector<std::string>{10}

