Topic: placement new and object reuse


Author: fjh@cs.mu.OZ.AU
Date: 1996/04/04
Raw View
To: C++ core language mailing list
Message c++std-core-6512

maxtal@Physics.usyd.edu.au (John Max Skaller) writes:

>>[Re 3.8/7:]
>>>OK.  On rereading it I can see that the important element is that it is
>>>talking about existing pointers.  Should it not also include references and
>>>if the original was a static or auto, its original 'name'?
>>
>>Yes.  You're right that the wording does not make this clear.
>>It should be clarified.
>
>        What I'd like to know is _what has the storage class
>got to do with it_??

It is very simple: only objects with static or auto storage class have names.
We were talking about adding words to 3.8/7 to clarify in the text what is
made clear in the example, that using the original name has the same
effect as using a pointer to the same storage.  These words could just
say "the original name, if any" rather than mentioning the storage class.

>        Writing in the store occupied by a const object which
>has not been destroyed may 'cause undefined behaviour' if the
>storage was write protected. This has NOTHING to do with
>the storage class, it is a universal of the memory model.

Oh, now you're talking about 3.8/9, not about 3.8/7.
Yes, I agree with what you say, but that guarantee is still not
sufficient to give compilers enough leeway for optimization;
hence we need 3.8/9 as well.

>        Furthermore, manually executing the destructor
>of a static or auto const object MUST release any write
>protection immediately PRIOR to the destructor being
>elaborated .. beacuse the destructor is permitted to
>modify the storage.

True.  But, consider the following example:

 struct foo {
  int member;
  foo(int i) { member = i; } // inline
  ~foo() { }   // inline
  ...
 };
 extern void bar(const foo &);
 extern void baz();

 int main() {
  {
  static const foo x(42);
  bar(x);
  ...
  }
  baz();
 }

Can the compiler place `x' in ROM?  The answer is yes only because of 3.8/9.
3.8/9 gives the compiler writer licence to not turn off write protection
before the destructor if the destructor is known to not write to the object.
Because of 3.8/9, this is OK by the "as if" rule.  But if 3.8/9 didn't
exist, it wouldn't be OK, because some other translation unit could contain

 foo *global;
 void bar(const foo &x) {
  global = const_cast<foo *>(&x);
 }
 void baz() {
  new (global) foo(43); // undefined behaviour by 3.8/9
 }

which would mean that the call to baz() would modify the storage for x.

The same sort of thing applies to

 extern void bar(const int &);
 extern void baz();

 int main() {
  { static const int x(42);
    bar(x);
    ...
  }
  baz();
 }

Here, you have a static constant int, surely the compiler should be allowed
to put it in ROM!  Fortunately this is true, but only because of 3.8/9.

Now, I guess you could argue for consistency that 3.8/9 should apply
to dynamically allocated storage too, but that would prevent any reuse
of storage use for placement new of const objects, which is probably
a bad idea, and there is no similar optimization argument, since
(a) it doesn't happen often enough to be an efficiency concern
and (b) compiler aren't going to be able to optimize such cases anyway.
Hence I think the existing rules are satisfactory.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]