Hacker News new | past | comments | ask | show | jobs | submit login
C++ Frequently Questioned Answers (yosefk.com)
60 points by kmavm on May 11, 2009 | hide | past | favorite | 73 comments



For those of you who are skimming: this is an attack job on C++

Instead of wading in to somebody else's religious war (and it's obviously personal for somebody to spend so much time finding fault with every item in the original FAQ), I'll just say: works great in some situations.

I was building a shell extension for Microsoft Windows several years ago. Booted up C++ and MVC, got up to speed on COM and shell extensions, and made some magic happen. Once I got up to speed (which took some time) I found I was just as productive in C++ as any other language. Same goes for a couple of other projects I've done in C++.

C++ is my favorite language, and it's a god-awful power tool of a beast. I don't use it regularly and don't plan to, but when you need it, it kicks ass. Most of the time, however, you need other stuff, like fast development times, ease-of-learning, common runtime, managed GC, and ease-of-understanding. Criticizing C++ for not having those things is completely missing the point of the language.


C++ is the first language I used, the one that pays my bills, and probably also still my favorite one. And while the FQA is an attack job, it's not just any attack job. It's done by a C++ expert and reading it will make you a better C++ programmer.


I also end up disagreeing with the FQA's underlying conclusions about C++. Nevertheless, I highly recommend everyone who uses C++ to read through the FQA in its entirety. It's well written and highly entertaining and gives you insight into many of the problems you can run into when using C++ which are glossed over by the FAQ.


If x - (fast_dev_time + ease_of_learning + common_runtime + managed_GC + easy_of_understanding) = kicks_ass, then what's x?

In other words, what redeems C++? What's the point of the language?


The redeeming quality of C++ is that there's nothing better in its specific niches.

The question to ask is:

- do you just care about results: I need a program that produces these outputs when given these inputs

- or do you care about what actually happens: I want the computer to do this, then this, then this, in exactly this way please.

...?

It's usually a good idea only to care about the former -- the essence of functional programming, higher-order functions, etc., is to be able to focus on the former as much as possible -- and so long as you only care about the former C++ doesn't have much to recommend it except in special circumstances.

On the other hand, there are times when what happens, exactly is important (eg: device drivers, other low-level code, directly interacting with hardware, etc.). In that scenario what C++ offers is a language that standardizes a lot of the functionality that most sufficiently-large raw-C programs have implemented in an ad-hoc basis.

There are other ways of doing low-level code, but at the present time C++ is the best of bunch (or at least the safest choice if you have an eye to the long term), not so much b/c it's particularly awesome but b/c the others have either faded away for business or political reasons, or b/c the others made limiting choices (C++ makes very few decisions for you, which means it's equally suited -- or unsuited -- to every task in its particularly niche).


I don't have a dog in this fight, but a major thesis of the article is that this is effectively not true for C++ (vs C) because the language is so complicated (thus the implementations so inconsistent/subtly incorrect) that it's incredibly difficult to determine exactly what the compiler is going to do with your input (or conversely, determine what in your input caused a given error in your object code.)


C and C++ (and a couple of other languages like Delphi) provide naked, unprotected pointers, which implies almost full control over memory and the CPU that no higher-level language can give. With pointers you are closer to hardware, in other words.

On top of that, C++ has damn powerful meta-language facilities no other language of any level has, which are, however, beneficial only when in good hands. It's too easy to misuse C++ unfortunately.


Gosh, I feel like a dinosaur. I didn't realize that pointers had become so exotic these days.

C++ is a fickle beast, but it is powerful and expressive. Like the grandparent, given that C++ is my best language, I do genuinely enjoy working in it when the situation fits.

For all of the talk of succinctness of Ruby, et al., I've had to rewrite a handful of Ruby lately in C++ for performance reasons and with a reasonable toolkit (e.g. Qt) really it wasn't much more code to get it done in C++ (about 30% more), for a runtime boost of about 1500%.

Qt's meta-object-compiler also adds things like introspection and call-by-name to QObject subclasses enabling some powerful things more typical of dynamic languages.

Granted, the real danger is that it blows up in the hands of someone not used to it, but it's a nice tool to have in your bag-o-tricks.


I agree with your first point.

However, I'll have to very strongly disagree with "C++ has damn powerful meta-language facilities no other language of any level has". C++ actually has terrible support for meta-language facilities.

It is inconceivable in my mind that C++'s support for that is anywhere near something like Common Lisp, so forget about it being the best in that respect. I'd love to know what parts of C++ are great meta-language facilities. If you say C++ macros I'll have to laugh. Hard.

</smuglispweenie>


Stepanov (i.e., Mr. C++ Standard Template Library) has said some comparably strong things about the expressiveness of C++ templates for the kinds of things expressed in STL, and he doesn't seem to be guilty of not investigating Lispy alternatives.

e.g., http://www.antiquark.com/escape/public_html/stepanovusa.html

There are various gnarly problems with C++'s model, some of which show up as gnarly problems in STL, even in fundamental stuff like implementing collections of refcounting pointers last time I looked. But as far as I can tell, every language which tries to get this correct within the language has some serious limitations or issues, arguably at least as bad, especially if like Stepanov one of your top priorities is eliminating every last bit of runtime overhead in the generated code. (E.g., implementing arrays of objects only as arrays of fixed-size pointers into variable-sized objects on the heap, as in typical CL and Java, is a no-go given STL priorities, and thus STL constantly wrestles with a bunch of problems that lots of other implementors have dodged by giving up on them.) As far as I know, no one has a comprehensively satisfactory solution for metalanguage facilities within the language.

Getting metalanguage correct by stepping outside the language and upstream from the compiler, writing a separate program to generate the target program, has been a solved problem as long as we've known how to write compilers in Turing-complete languages. That approach is sometimes used for app code in conventional languages, as in FFTW, and to some extent it's what Lispy macros do. But for some applications, including STL as I understand it, stepping upstream is unsatisfactory. Sometimes what you'd really like to do is have your code generator query the compiler about what the compiler knows. STL in particular, IIRC, wants to have its code generation depend on what the compiler knows about types and typedefs and so forth. In an ideal world it would be routine for code generators to be able to ask the compiler about other things, too, like dead code, namespaces, and safety and other pragmas.


Templates, the implicit ctor/dtor paradigm coupled with scoping, to name a few. I know Lisp has a unique feature - let's say, unity of code and data, but hey, there are plenty of languages with unique features not found in C++; nevertheless I think my statement still applies, that no language compares to C++ in terms of power of meta-language facilities. I think I understand Lisp and I'd be happy if we could avoid Lisp wars in this context.


Templates, the implicit ctor/dtor paradigm coupled with scoping, to name a few. I know Lisp has a unique feature - let's say, unity of code and data, but hey, there are plenty of languages with unique features not found in C++; nevertheless I think my statement still applies, that no language compares to C++ in terms of power of meta-language facilities.

Umm, lisp macros can implement all of C++ meta-language facilities and more, so how are said meta-language facilities more powerful?

And then there's the meta-language protocol....


  {
    X x, y;
    if (x > y)
      return;
    // some code ...
  }
where X has a destructor. I'm curious if you can do this in Lisp without explicitly calling the destructors (for x and y) in proper places - two places in this example.


unwind-protect handles this case. (Note that most lisps have GC so if freeing memory is the only reason you're calling the destructor, you don't need to do anything.)

http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec...

There's a reason why PG refers to non-lisps as "blub".

http://www.gigamonkeys.com/book/beyond-exception-handling-co... http://www.lisp.org/mop/index.html


unwind-protect is not the same. Destructors in C++ are part of custom data types, and unlike unwind-protect, they are "implied", which makes your code safer and more succinct. And no, it's not necessarily memory clean-up, of course.

C++ destructors are a powerful tool, you can create data types that otherwise would require support on the compiler's side.


> unwind-protect is not the same.

You're right - they're more powerful, but bringing that up didn't seem necessary.

> And no, it's not necessarily memory clean-up, of course.

Never said that they were. However, C++ programmers spend a fair amount of time worrying about/writing code for memory cleanup and destructors is where a lot of that time/code goes.

Folks using languages with GC don't do that nearly as much.

Destructructors are only implied for scope-allocated variables. By tying value lifetime to variable scope, C++ gets to do certain things, but as a result, programmers have to do certain work.

Lisp values are not tied to variable scope, so complaining that lisp doesn't have mechanisms for values that are tied to scope is sort of like complaining that a hovercraft doesn't have a parking brake.

> C++ destructors are a powerful tool, you can create data types that otherwise would require support on the compiler's side.

Actually, they're just a mechanism for calling code when a value "goes away". That's almost required for a language with manual memory management but unnecessary for languages with GC.

However, destructors are also the only way that C++ has for automatically calling code. Other languages have other, more general, mechanisms.


I see what you are saying, but unfortunately garbage collectors in their present form are more evil than good. They are fine in some situations, but may turn to a problem in others. For example, you may get very undesirable effects if you are creating and destroying a large number of objects in a time-critical application (a game, etc).

So, languages that provide no way of controlling allocation have relatively limited application compared to those that do provide full control over memory allocation.

By "relatively limited" I mean just relatively, that is, the reason Python, Ruby, Perl, PHP, Java, C# and Lisp with their GC facility exist is that it works most of the time, but there are certain areas where you have no choice other than C/C++. Kernels, compilers (including Lisp compilers), game engines, everything that deals with hardware, image, audio and video processing, etc etc.

This is an endless list where you really have no choice. Try to write a VST plug-in in Lisp, for example, that would add a reverb and will be able to do it on 8 audio channels in real-time on a 3GHz CPU.


> I see what you are saying, but unfortunately garbage collectors in their present form are more evil than good.

Wrong

> They are fine in some situations, but may turn to a problem in others.

Correct.

> For example, you may get very undesirable effects if you are creating and destroying a large number of objects in a time-critical application (a game, etc).

Not if you're using a reasonable real-time GC.

If allocation and reuse is occuring, memory management code is being executed.

GCs tend to run a bit slower, but you get faster development. Sometimes that's a good trade, and sometimes it isn't. (My real-time friends are correct when they say that late answers are wrong answers. However, it's also true that wrong answers are wrong answers.)

> compilers (including Lisp compilers)

Wrong again.

> everything that deals with hardware, image, audio and video processing

Wrong again. (Yes, lots of such systems are built with C/C++ but folks have done them with GC languages.)

And, our python friends have figured out that one can use C/C++ as an extension language for the heavy processing, where very little memory management occurs, and python everywhere else, getting the benefit of both worlds.

This is important because, when you get down to it, most of the applications that have lots of signal processing and the like are actually a couple of time-critical small kernels surrounded by lots of other code. Said other code dominates development time so GC for it is a big win.

> game engines

Yes and no, because "game engine" covers a wide range of things (from physics and rendering through high level "AI") and it depends on the available processing power.


I remember seeing exactly the same argument wrt assembly language vs C.

One interesting thing about the "performance is everything" crowd is how many of them use gcc even though there are other compilers for many ISAs that deliver significantly better performance.


> There's a reason why PG refers to non-lisps as "blub".

Where exactly did PG say that all non-Lisps are "blub", whatever that means?


I mis-spoke. He actually said that blub programmers found it hard to see certain things.

http://www.paulgraham.com/avg.html


I love advanced math.

But 99% of my life can be managed just fine with addition, subtraction, multiplication, and division.

It's that other 1%, though, where more advanced math kicks ass. If you've never seen it or watch it happen it's hard to describe how cool it is. With C++ you're controlling the CPU at a level just above machine language.

I love advanced math, but I rarely ever use it. Advanced math kicks ass.


It is seldom a good idea, or even sane, to choose to machine something out of titanium (or beryllium). But sometimes there are reasons.

I think C++ does a decent job of being as logically expressive as practical while still supporting C-level memory micromanagement. Typically exposing C-level memory micromanagement issues is a bug, but occasionally it's a feature. So to me, the point of C++ is to express abstractions like polymorphism and exceptions in the same few pages of code as low level memory operations. How often do I want to do that? Not very often, but it can happen.

Also, while C++ is very hairy and I wouldn't want to have to implement it, C++ seems to be implementable enough and standard enough that it may be usefully supported on a platform well before other more expressive languages. Perhaps it's because a lot of the C++ hair is frontend target-independent stuff like parsing and templates, so that once you've ported the C backend you're almost done porting C++ too? Dunno for sure why, but it seems to happen: e.g., it was my impression on my Atari ST many many years ago, and is my casual impression that something similar happened for the Arduino more recently.

C++ is admittedly a weird mess in various ways, but given the choice of source almost-compatibility with C (which I don't particularly value, but which I can at least understand) and C-level linkers (which I have mixed feelings about) a mess seems inevitable. Thus, I still consider it an impressive design.

Occsionally I've seen IMO-excessively broad claims that higher level languages are the best. It sometimes makes me think I might be able to cook up an example where C++ would be hard to beat: a small backtracking search problem where trailing operations (in the sense of "trailing" that you'll see if you Google "trailing backtracking") are in the inner loop. Take this thought of mine with a generous amount of salt, because I've never boiled it down to a really clean challenge. OTOH, I have at least implemented such search in several languages, and I even did a few casual benchmarks --- but 10+ years ago, when performance tradeoffs were rather different.

That's a particular case of a general theme where C-level programming could win: performance dominated by a very simple memory allocation regularity (LIFO, in this case) that the GC doesn't know about. (This theme also involves the precondition that you should care more about a factor of 2 in performance than a factor of 2 in programmer time, which often doesn't hold.) In many instances of this theme, the accreted featuritis bloat of C++ would be overkill, so you'd prefer C. In this instance, though, placement new() of polymorphic objects into LIFO-allocated raw memory is more expressive than anything I can see how to do in C.

Now, we should not forget that many programmers can go all year without running into a single problem where a factor of 2 in performance is worth a factor of 2 in programmer time. And we should not forget that even the ones who need to care deeply about performance often find it's not determined by a few low-level hotspots where low-level tweaking helps. But in some subfields, it's not too unusual to rationally choose to micromanage stuff at the level of C/C++. (I nominate the subfields of embedded programming and compute-heavy search from personal experience, and Quake/Unreal-like engine programming by reputation; I also explicitly do not nominate implementing web browsers, ow ow ow.)

It's harder to think of reasons I'd choose to write sizable programs in C++ (other than the compelling but unsatisfying accidental-seeming reason of early availability on a platform). One reason, though, is that there are many subproblems for which the choice of language doesn't matter all that much. E.g., Fortran is adequately expressive for a lot of the stuff in a book like _Numerical Recipes_, and you can famously write Fortran in (almost) any language. Because of this, I sometimes encounter a program where some key subproblem really cries for a particular style of language, possibly C++, and then I can be language-agnostic about solving the other subproblems, not minding writing it in whatever language I chose for the key part.


> What's the point of the language?

It's a drop-in replacement for C that is much more powerful and succinct.


That's the theory. The reality is that it's not more succinct and it's not significantly more powerful in most cases. Yes, there are some neat things you can do with templates (and I do), and some of the syntactic sugar things you get with objects and overloading and namespaces are nice, but there's nothing that you can do in C++ that you can't do equally well in C.

That said, C++ is in no way a "drop-in replacement" for C. What makes C++ "interesting" is that most of the time, you can drop C code into a C++ program and it will just work. Of course, you can do the same thing with Objective C, and the object model behind Objective C is much more sane.


> but there's nothing that you can do in C++ that you can't do equally well in C.

I'm shocked you're saying this in seriousness. C is a simple language lacking a large number of constructs and compiler safety features of C++. You might as well argue that BASIC is just as powerful as Python.

Inherently OOP problems like large simulations with huge class hierarchies could not realistically be done in C. The C++ frameworks for writing servers have no parallel in C because the language lacks required abstractions.

I have never seen C code that could not be rewritten more clearly in C++.


IMO, C++ offers no useful compiler safety features. One of the most celebrated "safety features" is const correctness. That's caused more pain in my experience than any possible value that it supports (and it has also resulted in a lot of unnecessary duplicated boilerplate code).

Templates, while useful and (sometimes) fun (as long as you're not having to debug them), aren't as interesting as having a real dynamic language like Python or Ruby.

I'd argue that your statement about "Inherently OOP problems" is incorrect from the first word. IMO, there's no such thing as a problem that's "inherently OOP"; there are problems which may be modeled easier in OO, but there's no problem that OOP solves that can't be solved a different way. (Why does a large simulation require a huge class hierarchy in any case? Maybe you're just Doing It Wrong.) There's also an assumption that C can't do OO, which is patently false; it's just not sugared for you like in C++.

I'd love to see what "required abstractions" you think that C++ provides, because I just simply don't see them. Except maybe namespaces. Overloading is nice, but not a necessary condition. References are just a mess. Templates are overkill for a lot of things. RTTI in C++ is a joke, especially if you're working cross-platform (and dynamic_cast on older versions of g++ just don't work, and sometimes you just can't escape those older versions).

All that said, I write C++ in my day job. A lot of it. But I don't pretend that anything I'm doing in C++ couldn't be done in C, possibly better and cleaner. We're designing a new set of APIs for plug-ins in our product, and we're moving toward a clean set of C-based APIs because they're (a) more portable across platforms and (b) more portable across languages so that we don't force people who want to write plug-ins for our product to use C++.


The author, Yossi Kreinin, is also one of the most underrated bloggers about software implementation on the planet. Before dismissing him as a one-trick pony language bigot, please sample http://www.yosefk.com/blog/ a bit. http://www.yosefk.com/blog/extreme-programming-explained.htm.... is just waiting to be dusted off and resubmitted by some enterprising young news.yc karma junky.


Fascinating that Yossi Kreinin hates Boost libraries so much. I have had my share of problems with them (slooooooow compilation and horrible template compiler error messages, mainly), but the Boost.Spirit parser library turned out to have been a lifesaver. I needed to parse JSON in a C++ system, had Boost available, but could not realistically install any other external library dependencies. Well --- the TinyJSON (http://blog.beef.de/projects/tinyjson/) looks a little funky thanks to all the templates and operator overloading magic, but it works well and I dropped it into the system as a header file. Problem solved.

I'd make heavier use of Boost.Filesystem, too, but I'm stuck deploying with an older version of Boost which lacks a few essentials. I never understood the messiness of concatenating path strings by hand until I was forced to stop using os.path (Python) and java.io.File (Java, Clojure).


Templates taking too long to compile and producing ridiculous error messages is actually one of, if not the, major complaints Yossi has about C++, though. One of the rarely spoken of differences between C and C++ is that the latter has a ludicrously slower compile leg of the compile/edit/debug cycle, and once you start digging into it, the slowness of compilation is built into the language (basically, matching template specializations is computationally hard), and is not an artifact of so-called "poor implementations."


Oh, his Cardinal Programming Jokes have been here already, but thanks for reminding, this rare and awesome blog is somewhere between the worlds of technology and bed-time fiction.


It's probably more important to have a good set of coding guidelines when writing C++ code than with other languages, but there's no reason not to write new projects in C++ if it's the best language for the task and team.

Voxli is built on C++ and boost. We make liberal use of scoped_ptr and shared_ptr where appropriate and we have yet to experience resource leaks in our client.


This.

Actually to add to your comment, it's not just good, but a MUST to have a set of good coding guidelines. The language is complex for a reason, you tell the Compiler EXACTLY what you want it to do, and this takes away overhead from the compiler trying to guess. It's a trade off between the convenience to the programmer to the performance of the application.

C++ isn't perfect, it's not meant for everything. But for fast, large, and complex systems, C++ is one of the best ways to go about it.


C++ is so not perfect and is definitely not for large scale development. Read this: http://labs.mudynamics.com/2007/07/23/writing-c-within-ruby/


C++ is so not perfect and is definitely not for large scale development

The article you posted is a interesting concept, but it's unproven, and seems a bit silly.

Lets consider some "large scale development" in C++ that's proven, fast, stable, scalable, and here to stay. Not C, But C++

* Adobe Software * Autodesk Software * CERN's Data Analysis Software * Google Chrome * Firefox and Thunderbird * MySQL * Java HotSpot VM * Majority of the large scale, succesful games out there (Doom 3, WoW, etc, etc) * Etc

Tell me which one of those are not large scale development? I excluded things like Microsoft OS's (since their half and half mix of C and C++).

Lot of the even larger scale applications are C/Pascal because they've been around for much longer (ex *nix projects), and higher performance. C++ offers very much the same, except on top a richer set of features and keeps the coders a bit more sane. No one really uses PURE C++, it's always a mix of C C++, but it's one of the very few languages out there that match in performance to the original C.

(counter that with Java, if so tell me why only such a small number of VERY LARGE software systems is written in it, it's fast as C/C++ now right? right?). But don't counter it with C-Ruby... because, just don't.


Reality, however, contradicts you. C++ is one of the only languages out there PROVEN in the field by being used in thousands of large-scale developments.

Operating Systems, Office applications, Browsers, Search Engines, etc. - aren't these large scale?!


You forgot that C++ is used in Jet Fighters, and other little inconsequential things such as that ;)

cite: http://www.research.att.com/~bs/JSF-AV-rules.pdf

Edit... not just any jet fighter, but the most complex jet fighter ever devised by the mind of mankind. That's why C++ kicks ass ;)


Linux C, BSD C, really I can't think of a truly large stable system written in C++. There are plenty written in C.

Edit: Thanks, I didn't know there was a C++ OS out there. Though to be fair to C++ it hasn't been around as long nor been as stable as C (from C with classes to C with classes exceptions and templates.)


Symbian OS is written in C++, excluding some internals of the kernel written in C/ARM assembly. I was told when I worked there (3-4 years ago) that the entire code base (including test code, variant code etc.) is on the order of 50 million lines of code. So definitely large. Stable? A matter of opinion.


Try Cobol. Or C. Or Assembler. Or Fortran. Those languages are also used in large projects since ages. But what does that tell us?


Tells us that they are mature, strong, proven programming languages and we should use them in large-scale developement UNLESS we have a better alternative, ALSO mature, strong and proven. Thankfully, we do: C++


Your argument could be used to prove Java superior to C++, too.


Also worth reading (edit: if you've got an hour to kill and care about the subject): http://groups.google.com/group/comp.lang.c++.moderated/brows...

The author defends his position pretty coherently and civilly; you can disagree with his conclusions but calling him a troll or an idiot is certainly not warranted.


On a quite related note, I like this page as well:

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

;)


If you're criticising something as vast as the C++ FAQ lite and find issue with every single claim, then you are bigoted and your review probably isn't worth it.


This is both a bad argument and kind of lacking a sense of humor, since programmers do this (point by point rebuttals) all the time (see: every popular thread on the LKML, ever)


Even if programmers do something all the time, that doesn't mean it's right. The reason is simple: every opinion has arguments in favor of it. If someone offers five arguments in favor of an opinion, usually at least two are reasonable. If someone attempts to rebuke all five points, they're usually being unreasonable. It's also counterproductive, because bad counter-arguments call for counter-counter-arguments, which detracts from the actual points under discussoin. If you think an argument isn't persuasive and doesn't have much weight, then that is what you should say, instead of searching for some nitpicky way to counter the argument, usually ending up in discussions about semantics because you actually agree on the point.

As for this article: if this was intended to be humorous, then it contains far too much that seems to have been intended seriously, for my taste. After a few points he could have stopped beating the dead horse.

Wrapping criticism in humor is an annoying strategy similar to the 'poisoning the well' fallacy: as soon as someone tries to start a discussion, you can go "where's your sense of humor?" and your humorously wrapped argument remains unchallenged. That gets under my skin and may have impaired my humor detecting capabilities here.


I don't think your first paragraph follows (I think you can certainly contest every assertion in favor of a position without being illogical), although I agree the style is usually unproductive. I'd rather not get into debating it here, though.

The 'humor' I was referring to wasn't in the article (which is pretty bland) but in the fact that hey, this fits the stereotypical image of a programmer: slightly OCD (nitpicky) and lacking social grace. You'd think we'd be used to it :)


I think it's a bad practice in general, as it encourages nit-picking the small details and missing the main point of what someone says.


A programmer who isn't a nitpicker is a lousy programmer. Computers don't get the "main point" of what someone says. I'm not much of a nitpicker, which is my biggest problem when coding.


Discussions with humans is an entirely different domain than programming computers. I get the same urges to argue with someone point-by-point as anyone else does, and I try to quell it so that a useful discussion can take place.


Wish there were more sites like this. We mostly just believe the answers we recieve.


I feel like people miss one of the main points of this FQA. The author repeatedly asserts that most people who think they need C++ do so because they think they need the performance it can offer. Most of these people, however, don't actually need the extra performance and would be much better off with a higher level language. Those that actually do need the performance and know what they are doing would be better off just using C with assembler.

In many ways, I think he is right. C++ tries to be high-level, low-level and everything in between all at once, and the end result can bring a lot of potentially unnecessary frustration to programmers. There are several projects, such as LLVM, for example, that get by using a "tasteful subset" of C++, and I would be interested in learning what that subset is.


"Unfortunately, you can't tell the class of a C++ object given a pointer to it at run time....which is why you can't automatically collect the garbage of C++ programs."

What nonsense. Here's what I learned from this link: trolling isn't as effective when it requires the trollee to read 10 pages of text.

This is garbage. Please flag it for collection.


Just because you disagree with something does not automatically make it a troll.


AFAIK it's reasonably well known as an unintentional troll - there was a stackoverflow question about the FQA (still looking for the link) that basically mooted almost every point.

I was reading it as a neutral party, however some very knowledgeable C++ appeared to convince all comers that the FQA is either based on ignorance or is disingenuous.


I also once tried referencing the C++ FQA on stackoverflow and was quickly downvoted. Maybe SO is just the wrong place to mention it, probably because of a C++ bias from the high percentage of SO users who develop on MS platforms.


Maybe this is it:

http://stackoverflow.com/questions/385297/whats-wrong-with-c...

Summarizing: "C++ is hard but makes some things possible that aren't in other languages."

The FQA dude is a troll: he criticizes without offering better alternatives, ignoring tradeoffs and considerations and overlooking any advantages offered by C++.


My disagreement has nothing to do with it -- the quoted remark was completely without basis in fact.


"Unfortunately, you can't tell the class of a C++ object given a pointer to it at run time....which is why you can't automatically collect the garbage of C++ programs."

That's a somewhat self-serving use of ellipses. Here's the actual text:

"Unfortunately, you can't tell the class of a C++ object given a pointer to it at run time. So if you debug a crashed C++ program and find a pointer somewhere in its guts, and you don't know its type, you'll have to guess that "0000000600000005" is a Point. Which is completely obvious, because that's the way a pair of adjacent integers looks like in hexadecimal memory listings of a little endian 32 bit machine. And two adjacent integers might be a Point. Or some other two-integer structure. Or a part of a three-integer-and-a-float structure. Or they might be two unrelated numbers which just happen to be adjacent.

Which is why you can't automatically collect the garbage of C++ programs."

Which part are you claiming is wrong? (Be careful.) The entire first paragraph even Bjarne Stroustrup would agree with once he was done hemming and hawing. Post-mortem inference of types of dynamic objects in C++ programs is undecidable. In higher-level OO languages, memory is organized as framed objects, not as a bag of bytes. The main thrust of this questioned answer had nothing to do with GC.

And he's right about this being what makes GC and C++ bad fits for one another, too, though he skipped a few steps. Getting out the sock puppets, without the ability to tell the type of an in-memory object, you can't compact the heap. If you want to move an object, you can't just assume anything in memory with the bit pattern of that object's address is a pointer, because it might be two shorts or a double or whatever that happens to have that bit pattern.

While conservative, non-compacting garbage collectors can be built in theory, they're too slow in practice. Check out the source to Hans Boehm's C/C++ collector; it stops all the threads in the process, and analyzes liveness starting from each thread's CPU registers, each thread's entire stack, and the entire static data segment. By the implementors' own admission, this will not scale to large numbers of threads, or large address spaces. Even if this approach is refined significantly, if your garbage-collected program lives long enough, you need compacting garbage collection, or fragmentation will kill you just as surely as exhaustion would have.

And if you are so convinced that performant, general purpose GC can be dropped into large C++ codebases, you have a straightforward way of both shutting me up, and having a very interesting ycombinator startup. A drop-in operator new overload that does compacting, generational, safe GC would have a readymade market, with very deep pockets, from companies stuck maintaining enormous piles of C++ code with intractable memory management bugs.


I used ellipses because none of the quoted argument was correct, and there was no point making a long quote, when a short one would suffice.

First, the premise was false: you can tell the type of a pointer to a dynamic object -- you use RTTI. You don't have to "guess" that the object is a Point, because you can use dynamic_cast<>() or typeid() to tell for sure.

Second, the conclusion was false: it is possible to write a garbage collector for C++. You cited a very popular one in your response.

So what do we have? You can tell the type of an object at runtime, and you can write a garbage collector for C++. When both the premise and the conclusion of an argument are incorrect, well...let's just say that it's hard to be less correct than that. It's Not Even Wrong.

As for your defense, let's be clear: you're not suggesting that it's impossible to "automatically collect the garbage of C++ programs" -- you're arguing that it's impossible to do it efficiently. I dispute that argument, too, but it has absolutely nothing to do with the comment that I quoted. It's a straw-man.

The bottom line is that the quoted statement was absurd, and you're only setting up a straw-man (about the efficiency of C++ GCs, and about the ability to drop them into large codebases.) We could perhaps have an interesting discussion about those topics, but our discussion wouldn't make the original article any less of a flame-bait.


So does C++ really guarantee that every valid pointer in a program will always point to the start of an object with an attached RTTI structure, and not for example somewhere into the middle of an array of integers that just happen to mimic the signature of an object with RTTI?


What does that have to do with the question of whether it's possible to infer types in C++ at runtime? What does it have to do with the question of whether it's possible to have garbage collection in C++?

This debate is becoming inane. I challenge you to name another language that allows for arbitrary references to blocks of memory, while still guaranteeing that the data type of said references can always be correctly inferred. You're just nit-picking.


I challenge you to name another language that allows for arbitrary references to blocks of memory, while still guaranteeing that the data type of said references can always be correctly inferred

That's exactly the point! Allowing arbitrary references to blocks of memory means inferring types is hard! That's exactly what the FQA entry is saying! ... I'm stunned at how adamant you're being about this. Do you really think the author doesn't know about RTTI? Seriously, dude, you're wrong.


You decide where the pointer points, and how the compiler should start treating the data. That's the point of the pointer, you are given total control.


How does the existence of RTTI falsify the statement "you can't tell the class of a C++ object given a pointer to it at run time"? Not all objects are instances of classes with vtables.


Because RTTI lets you tell the class of a C++ object given a pointer to it at run time. The statement was false. This is not a subtle argument.

Again, you're trying to set up a straw man: the question is not whether or not it's efficient to do type inference in C++ (for the record: it's NOT any more efficient in a dynamic language), the question is whether it's possible at all.

It is possible to do so, the original argument was incorrect, and you're trying to have an entirely different debate.


Dude, RTTI only works for classes with virtual functions or their derivatives.


Yes, I know. You're arguing that not all classes have vtables. I'm arguing that there's no reason that they can't, save for efficiency concerns. And if you're so concerned about efficiency that vtables are a burden, then you're already in a situation where an interpreted language is inappropriate for your needs.


Now you're arguing something different. Just because all classes can, doesn't mean that they do, or that a general purpose tool (like, say, a garbage collector) can assume that they do. It's not a question of efficiency, it's a question of what the language allows. If you're saying "everything has to have a vtable", then you aren't talking about C++.


This is C++. Implement your own deconstructor, and manage your own damn memory.

I would probably use Boost's smart pointers to handle the reference counting though.


No, GP's point is that there are garbage collectors for C++. I believe Stroustrup even mentions one in The C++ Programming Kanguage. Furthermore, you CAN tell the type of an object given a pointer to it, assuming it has at least one virtual function, using the typeid operator. As the GP said, the original quote is nonsense.


assuming it has at least one virtual function

Which you can't do. Seriously, when did it become okay to call out a problem with the general case as nonsense because there's a specific case that avoids the issue?




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

Search: