home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.std.c++
- Path: sparky!uunet!microsoft!hexnut!jimad
- From: jimad@microsoft.com (Jim Adcock)
- Subject: Re: return values and destructors
- Message-ID: <1992Nov12.224756.9656@microsoft.com>
- Date: 12 Nov 92 22:47:56 GMT
- Organization: Microsoft Corporation
- References: <BxKs87.417@scd.hp.com>
- Lines: 117
-
- In article <BxKs87.417@scd.hp.com> vinoski@ch.apollo.hp.com (Stephen Vinoski) writes:
- |
- |In section 6.6.3 on page 90 the ARM states:
- |
- |"A return statement with an expression can be used only in functions
- |returning a value; the value of the expression is returned to the
- |caller of the function."
-
- First note, that like ANSI-C, C++ does not seem to require return-by-copy,
- allowing instead return-by value. This in no way, however, excuses
- compiler from making a copy of the returned value of the expression if
- such a copy is required in order to maintain the correct value of that
- return expression as evaluated in sequence and in scope.
-
- |Given the statement
- |
- | return foo;
- |
- |where foo is an object with some value, does the statement from the
- |ARM mean that the compiler *must* return the value that foo has in the
- |return statement, rather than the value foo might have at some point
- |after the destructors for local automatic objects have been executed?
-
- Consider the not-uncommon case where foo is an auto-variable of the
- function returning foo and foo is of a class with a dtor. This common
- case demonstrates that the scope that the return value expression must
- the same as the scope that the return expression is in. Otherwise foo
- would be dead before evaluated. Thus evaluation of the expression
- must occur before exiting scope. Dtoring occurs *at* exit of scope.
- Thus the evaluation of the expression occurs before dtoring. If dtoring
- then affects an evaluation that must occur before dtoring, clearly
- this must be a compiler bug. If the rules were otherwise you could
- not reliably return-by-value an auto-variable object of a class with a dtor.
-
- |Consider this example:
- |
- |template<class T>
- |class A
- |{
- | public:
- | A(T *p) : ptr(p) {}
- | ~A() {if (ptr) *ptr = 0;}
- | private:
- | T *ptr;
- |};
- |
- |
- |int
- |func1()
- |{
- | int x = 10;
- | A<int> a(&x);
- | return x;
- |}
- |
- |
- |func1() returns 0, not 10, even though the value of
- |x in the return statement is clearly 10. The value of x is changed to
- |0 due to the destructor of the A object going out of scope at the end
- |of the function.
-
- As you point out the value of x in the return statement is clearly 10.
- The evaluation of the return expression then is the evaluation of x
- is clearly 10. The returned value is the evaluation of the return expression
- is the evaluation of x is clearly 10. Anything else is clearly a bug.
-
- |What's more interesting is that if a func2() is created that returns
- |by value an object of a class type with a constructor and destructor,
- |the desired value is returned because of the generation of a
- |temporary:
- |
- |class B
- |{
- | public:
- | B(int x) : val(x) {}
- | ~B() {}
- | void operator=(int x) {val = x;}
- | operator int() {return val;}
- | private:
- | int val;
- |};
- |
- |B
- |func2()
- |{
- | B b(10);
- | A<B> a(&b); // same A as above
- | return b;
- |}
- |
- |
- |In this case, func2() returns a B whose val member has a value of 10,
- |due to the generation of a temporary, even though the same A
- |destructor sets the value to 0.
- |
- |Shouldn't both of these cases perform the same way?
-
- Yes.
-
- |Is this a compiler bug?
-
- Bug.
-
- |Shouldn't the value of the return expression be returned to the
- |caller regardless of side effects of destructors for auto objects?
-
- Yes because clearly evaluation of an expression in scope, including
- the evaluation of the expression in the return statement, are evaluated
- in scope, and dtor'ing doesn't happen until exiting of scope, which is later.
-
- |Does the language enforce any of this?
-
- If when the spec is complete, it ought to be complete and specific enough
- to make these issues unarguable. These issues of return-by-value,
- return-by-copy, etc, have been kicking around for many years in the
- ANSI-C committee and now C++, and ought to just be nailed down once and
- for all.
-