Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!sunybcs!oswego!news From: dl@g.g.oswego.edu (Doug Lea) Newsgroups: comp.lang.c++ Subject: Re: Strings Message-ID: Date: 25 Oct 89 10:25:56 GMT References: <10050@alice.UUCP> Sender: news@oswego.Oswego.EDU (Network News) Reply-To: dl@oswego.edu Distribution: comp Organization: SUNY Oswego Lines: 88 In-reply-to: ark@alice.UUCP's message of 24 Oct 89 18:50:31 GMT I had written... > > String& addeol(String& s) { s += "\n"; return s; } > > > main() > > { > > String a, b; //... > > String c = addeol(a+b); > > //... > > } > > > which would be illegal if operator+ returned a const String. (Yes, > > the form of `addeol' is contrived, but not indefensible.) > Andy replied... > The trouble with the example is that the value of a+b is a temporary > that can be destroyed as soon as addeol() returns. Thus it seems > to me that it should be OK for a compiler to generate code that > looks like this: > > evaluate a+b into a temporary T > call addeol(T) and save a reference to the result > destroy T > copy the saved result of addeol() into c > > In this case, the `saved result' of addeol will have been destroyed > before copying it, so c will be garbage. > > You might say that this argues that the destruction of the temporary > that holds a+b should be deferred until later. Unfortunately, doing > that doesn't eliminate the problem, it just makes it less likely. > It's hard to be sure. In my (draft) copy of the 2.0 Reference Manual, section 12.2, it says The compiler must ensure that a temporary object is destroyed. There are only two things that can be done with a temporary: fetch its value (implicitly copying it) to use in some other expresssion, or bind a reference to it. If the value of a temporary is fetched, that temporary is dead and can be destroyed immediately. If a reference is bound to the temporary, the temporary must not be destroyed until the reference is. This destruction must take place before exit from the scope in which the temporary is created. This statement does not explicitly address what happens with multiple references: addeol makes a ref of the temp holding a+b, and in turn binds another ref to it (the return value). The `right' thing to do is to not kill the temp until the return val reference is destroyed (after construction into c). Of course, the compiler cannot know this if addeol is not inline or is an extern, but I assumed that the above rule requires that a compiler play it safe, and not kill the temp until all references spawned from expressions involving it die. But I see that your interpretation could also be right. As I too weakly implied elsewhere in my last note, I think the temp rules could be strengthened by generalizing this paragraph via the simple statement that a temporary (like any normal variable) may be destroyed only when a compiler can prove that it is no longer useful, or at the end of the enclosing scope, whichever comes first. This rule is similar to those used in other languages. The rule requires that if a temp is involved in any reference-returning member or top-level function, or a reference is bound to any of its parts, it should live. It might also be allowed to live if the compiler can prove that it will be recomputed/reused later in the same block (as may be discovered via available expression analysis), thus killing off the recomputation. On the other hand, it might be killed immediately if it is never used (e.g., the single statement `a+b;'), a possibility ignored in the above. This restatement would thus cover the current cases, and also allow the possiblity of a smarter compiler doing smarter things. (I guess I should add that, as we've gone over before, a rule like this also helps legitimize and extend the current practice of not generating X(X&)-based temporaries at all in some situations.) I should emphasize that the form of addeol is NOT one I recommend. Oh, I should clarify another remark in my last note: OPERAND evaluation order is undefined in C++ for `cout << dec(10) << dec(20)'. OPERATOR evaluation is, of course, left-to-right. -- Doug Lea, Computer Science Dept., SUNY Oswego, Oswego, NY, 13126 (315)341-2367 email: dl@oswego.edu or dl%oswego.edu@nisc.nyser.net UUCP :...cornell!devvax!oswego!dl or ...rutgers!sunybcs!oswego!dl