Path: utzoo!telly!lethe!dptcdc!attcan!uunet!tut.cis.ohio-state.edu!ROCKY.OSWEGO.EDU!dl From: dl@ROCKY.OSWEGO.EDU (Doug Lea) Newsgroups: gnu.g++.bug Subject: G++ 1.34.1 named return values (and related 1.34.1 problems) Message-ID: <8903181339.AA27932@rocky> Date: 18 Mar 89 13:39:42 GMT References: <21944@shemp.CS.UCLA.EDU> Sender: daemon@tut.cis.ohio-state.edu Reply-To: dl@rocky.oswego.edu Distribution: gnu Organization: GNUs Not Usenet Lines: 96 I think Michael's documentation was wrong (or at least misleading). If you have a named return value, you should *only* return via `return' or by falling-off-the-edge. (Otherwise, in your example, it says to make tmp out of itself using A(A&), which is not very sensible.) See below. [Anyone wanting further rationale for this construct should see my recent comp.lang.c++ postings.] A few other notes about my experience with 1.34.1+ (1.34.1 plus Michael's 2 posted patches) on a vax750, 4.3BSD: The -felide-constructors switch seems buggy. All libg++ problems I've been able to diagnose when testing this switch appear due to the kind of local-variable-trashing behavior shown below. Note, however, that constructs both of the form `var a = fun()' and `var a(fun())' now, in 1.34.1, produce the same results (no temps!) with or without this switch. Using the -fsave-memoized switch also seems buggy. Several libg++ tests (test5, intList.cc) fail to compile with this switch. By the way, in the example, if you #include , you ought to use `cout.form(...)' (or `cout << form(...)') instead of `printf' to ensure proper flushing of output on program termination (on most machines, this apparently only matters if you are redirecting output). -Doug ------ file A.cc (a revision of rjc's example) #include struct A { int i; A(int x) { cout.form("A(%d)\n", x); i = x; }; A(A& x) { cout.form("A(A& x), x.i == %d\n", x.i); i = x.i; }; ~A(void) { cout.form("~A(%d)\n", i); }; void operator += (A& x) { cout.form("+=(%d, %d)\n", i, x.i); i += x.i; }; }; A foo () return tmp(4); // essentially equivalent to `tmp=4', // but explicitly use a constr. for clarity! { cout.form("foo(void), tmp.i == %d\n", tmp.i); return; // *not* `return tmp' } main() { A bar = 5; bar += foo(); cout.form("main(), bar.i == %d\n", bar.i); A baz = foo(); cout.form("main(), baz.i == %d\n", baz.i); A baz_con(foo()); cout.form("main(), baz_con.i == %d\n", baz_con.i); } -------- A correct compile/run without -felide-constructors R>g++ -g -O -finline-functions A.cc R>a.out A(5) A(4) foo(void), tmp.i == 4 +=(5, 4) ~A(4) main(), bar.i == 9 A(4) foo(void), tmp.i == 4 main(), baz.i == 4 A(4) foo(void), tmp.i == 4 main(), baz_con.i == 4 ~A(4) ~A(4) ~A(9) ----------- with -felide-constructors R>g++ -g -O -finline-functions -felide-constructors A.cc R>a.out A(5) A(4) foo(void), tmp.i == 4 +=(4, 4) # `bar' is trashed! main(), bar.i == 8 A(4) foo(void), tmp.i == 4 main(), baz.i == 4 A(4) foo(void), tmp.i == 4 main(), baz_con.i == 4 ~A(4) ~A(4) ~A(8)