I say this as a C++ programmer (C++ is essentially the only choice in the domain in which I currently work), but this really underscores how unreasonable C++ is for writing secure/high reliability applications. On the one hand, the compiler will curse you out for trying to use a non-const iterator in a const function (sheesh, what kind of an idiot are you, anyway)? On the other hand, you can read and write to every bit of memory allocated to your application, and it will stand by and do nothing. I think the number of applications which had buffer overflows at least at some point is statistically indistinguishable from 100%.<p>Try this hotel analogy: you go to a hotel in which you once stayed, and tell them that you're going to dump every bit of possessions and furnishings in all the rooms outside on the street, rifle through them, set them on fire, then photograph all their guests in the nude and distribute the pictures. Most hotels will object. C++ won't.
Eric Lippert is a prolific writer and is amazing at explaining anything related to computer programming. His blog is a MUST read for every .NET developer: <a href="http://blogs.msdn.com/b/ericlippert/" rel="nofollow">http://blogs.msdn.com/b/ericlippert/</a><p>I also follow Eric's activity on SO here:<p><a href="http://stackoverflow.com/users/88656/eric-lippert?tab=activity" rel="nofollow">http://stackoverflow.com/users/88656/eric-lippert?tab=activi...</a><p>Some of his answers which I liked:<p><a href="http://stackoverflow.com/questions/2704652/monad-in-plain-english-for-the-oop-programmer-with-no-fp-background/2704795#2704795" rel="nofollow">http://stackoverflow.com/questions/2704652/monad-in-plain-en...</a><p><a href="http://stackoverflow.com/questions/921180/how-can-i-ensure-that-a-division-of-integers-is-always-rounded-up/926806#926806" rel="nofollow">http://stackoverflow.com/questions/921180/how-can-i-ensure-t...</a><p><a href="http://stackoverflow.com/questions/5032081/coding-style-assignments-inside-expressions/5032287#5032287" rel="nofollow">http://stackoverflow.com/questions/5032081/coding-style-assi...</a><p>He is on HN as well:<p><a href="http://news.ycombinator.com/threads?id=ericlippert" rel="nofollow">http://news.ycombinator.com/threads?id=ericlippert</a>
I'll probably get downvoted, but I think elaborate real-life analogies like this are more likely to confuse novices than help them.<p>A better explanation in my opinion is to draw a diagram of a stack and showing that returning from a function just decreases a pointer. C++ programs don't scrub the top of the stack once you finish a function because it is a waste of time.<p>If another function was called before the 2nd call to foo(), then the variable on the stack would be overwritten.
I had a roommate in college who would write code like this. I (and several other people) tried to explain to him that he couldn't necessarily count on the pattern working all the time. His response was to say, "But it works here!" and continue abusing C++'s undefined behavior.<p>I stopped giving him help with his CS coursework in fairly short order.
Eric Lippert was one of the highlights of working at Microsoft. He was (and I'm sure, still is) very active on the internal C# mailing list. His answers are always very entertaining to read. He has a smugness that is deserved and not irritating (mostly :)), and inside the walls of MS he turns that smugness up quite a bit higher.
Great analogy and well written. We often see attempts at this style of explanation, but we usually fail at one or both of those qualities.<p>While I wish I saw more of this style of teaching in technical publications, it's admittedly rarely done well enough to convey the point.
I'm not sure I agree <i>entirely</i> with this explanation. He emphasises that this is unsafe behaviour that is protected against in safer languages - I've never heard it said that the use of pointers should be considered unsafe and there are also pointers in other languages that exclude things like multiple-inheritance and have garbage collection (which could be considered safer languages).<p>I like the room key analogy (almost) but I don't think it needs to be stolen and I don't think all the talk about policies and contracts is necessary at all.<p>It could simply say the thing you're returning is not the local variable. It is a pointer.<p>I have a box and instead of giving you the box I give you a key to the box. Anytime you want to use the contents of the box you must come over to the box and open it, but you can't take the box with you. If you want to put something in the box you just walk over and put it in - but here's the rub: you have no guarantees that you're the only one with a key. I could give out the key to a bunch of people so you don't know what will be in the box and who owns it.<p>Use with caution!
Local variables in C and C++ are just put on a stack (i.e. <i>the stack</i>) and its behavior is pretty predictable. For example:<p><pre><code> #include <stdio.h>
static int *foo(void)
{
int i = 42;
return &i;
}
static int *bar(void)
{
int i = 43;
return &i;
}
int main(void)
{
int *f = foo();
/* with next line commented out prints 42, with it, 43 */
bar();
int i = *f;
printf("%i\n", i);
return 0;
}
</code></pre>
Until you've made another function call that reuses that space on the stack you'll almost certainly still have valid values when accessing those local variables by address. Things are a bit vaguer in C++ where those variables may be objects which have destructors which have already been called.<p>Edit: Made it predictable, per caf's (correct) comment by adding:<p><pre><code> int i = *f;</code></pre>
A good analogy no doubt! But you should be careful when using analogies. Every behavior of the analogy might not be applicable to the original problem.<p>Analogies can only help make people "understand" something. Normal brains try to relate things to what it has learnt so far. So analogies seem to help. Analogies in themselves are not scientific explanations obviously.<p>A scientific/rational explanation to the question posed by the user would be - C++ makes no promise about the behavior of the program when out-of scope C++ variable is used. Obviously this explanation -a simple one is quite less dramatic.