home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / std / cplus / 1555 < prev    next >
Encoding:
Text File  |  1992-11-12  |  4.0 KB  |  128 lines

  1. Newsgroups: comp.std.c++
  2. Path: sparky!uunet!microsoft!hexnut!jimad
  3. From: jimad@microsoft.com (Jim Adcock)
  4. Subject: Re: return values and destructors
  5. Message-ID: <1992Nov12.224756.9656@microsoft.com>
  6. Date: 12 Nov 92 22:47:56 GMT
  7. Organization: Microsoft Corporation
  8. References: <BxKs87.417@scd.hp.com>
  9. Lines: 117
  10.  
  11. In article <BxKs87.417@scd.hp.com> vinoski@ch.apollo.hp.com (Stephen Vinoski) writes:
  12. |
  13. |In section 6.6.3 on page 90 the ARM states:
  14. |
  15. |"A return statement with an expression can be used only in functions
  16. |returning a value; the value of the expression is returned to the
  17. |caller of the function."
  18.  
  19. First note, that like ANSI-C, C++ does not seem to require return-by-copy,
  20. allowing instead return-by value.  This in no way, however, excuses
  21. compiler from making a copy of the returned value of the expression if
  22. such a copy is required in order to maintain the correct value of that
  23. return expression as evaluated in sequence and in scope.
  24.  
  25. |Given the statement
  26. |
  27. |    return foo;
  28. |
  29. |where foo is an object with some value, does the statement from the
  30. |ARM mean that the compiler *must* return the value that foo has in the
  31. |return statement, rather than the value foo might have at some point
  32. |after the destructors for local automatic objects have been executed?
  33.  
  34. Consider the not-uncommon case where foo is an auto-variable of the 
  35. function returning foo and foo is of a class with a dtor.  This common
  36. case demonstrates that the scope that the return value expression must 
  37. the same as the scope that the return expression is in.  Otherwise foo
  38. would be dead before evaluated.  Thus evaluation of the expression 
  39. must occur before exiting scope.  Dtoring occurs *at* exit of scope.  
  40. Thus the evaluation of the expression occurs before dtoring.  If dtoring 
  41. then affects an evaluation that must occur before dtoring, clearly 
  42. this must be a compiler bug.  If the rules were otherwise you could 
  43. not reliably return-by-value an auto-variable object of a class with a dtor.
  44.  
  45. |Consider this example:
  46. |
  47. |template<class T>
  48. |class A
  49. |{
  50. |  public:
  51. |    A(T *p) : ptr(p) {}
  52. |    ~A() {if (ptr) *ptr = 0;}
  53. |  private:
  54. |    T *ptr;
  55. |};
  56. |
  57. |
  58. |int
  59. |func1()
  60. |{
  61. |    int x = 10;
  62. |    A<int> a(&x);
  63. |    return x;
  64. |}
  65. |
  66. |
  67. |func1() returns 0, not 10, even though the value of
  68. |x in the return statement is clearly 10.  The value of x is changed to
  69. |0 due to the destructor of the A object going out of scope at the end
  70. |of the function.
  71.  
  72. As you point out the value of x in the return statement is clearly 10.
  73. The evaluation of the return expression then is the evaluation of x
  74. is clearly 10.  The returned value is the evaluation of the return expression
  75. is the evaluation of x is clearly 10.  Anything else is clearly a bug.
  76.  
  77. |What's more interesting is that if a func2() is created that returns
  78. |by value an object of a class type with a constructor and destructor,
  79. |the desired value is returned because of the generation of a
  80. |temporary:
  81. |
  82. |class B
  83. |{
  84. |  public:
  85. |    B(int x) : val(x) {}
  86. |    ~B() {}
  87. |    void operator=(int x) {val = x;}
  88. |    operator int() {return val;}
  89. |  private:
  90. |    int val;
  91. |};
  92. |
  93. |B
  94. |func2()
  95. |{
  96. |    B b(10);
  97. |    A<B> a(&b);    // same A as above
  98. |    return b;
  99. |}
  100. |
  101. |
  102. |In this case, func2() returns a B whose val member has a value of 10,
  103. |due to the generation of a temporary, even though the same A
  104. |destructor sets the value to 0.
  105. |
  106. |Shouldn't both of these cases perform the same way?  
  107.  
  108. Yes.
  109.  
  110. |Is this a compiler bug?  
  111.  
  112. Bug.
  113.  
  114. |Shouldn't the value of the return expression be returned to the
  115. |caller regardless of side effects of destructors for auto objects?
  116.  
  117. Yes because clearly evaluation of an expression in scope, including
  118. the evaluation of the expression in the return statement, are evaluated
  119. in scope, and dtor'ing doesn't happen until exiting of scope, which is later.
  120.  
  121. |Does the language enforce any of this?  
  122.  
  123. If when the spec is complete, it ought to be complete and specific enough
  124. to make these issues unarguable.  These issues of return-by-value, 
  125. return-by-copy, etc, have been kicking around for many years in the 
  126. ANSI-C committee and now C++, and ought to just be nailed down once and
  127. for all.
  128.