On Thu, Aug 22, 2013 at 6:16 PM, Mike Stump <mikest...@comcast.net> wrote: > On Aug 22, 2013, at 2:28 PM, Gabriel Dos Reis <g...@integrable-solutions.net> > wrote: >> On Thu, Aug 22, 2013 at 4:14 PM, Mike Stump <mikest...@comcast.net> wrote: >>> On Aug 22, 2013, at 9:45 AM, Gabriel Dos Reis >>> <g...@integrable-solutions.net> wrote: >>>>> I.e. can I have something like >>>>> >>>>> int a; >>>>> test() >>>>> { >>>>> int *b=new (int); >>>>> } >>>>> >>>>> with custom implementation of new that returns &a? >>>> >>>> If the user-supplied operator new returns &a, then it must >>>> also ensure that 'a' is not used anywhere else -- e.g. I you can't >>>> do lvalue-to-value conversion on 'a' to see what is written there. >>> >>> This is wrong, in the c++97 standard there is no such limitation or >>> restriction. >> >> Please, elaborate. > > Sure, there is no wording that limits as you describe. There is a limit for > polymorphic classes and classes with virtual bases (See [class.cdtor], but > that is due to the vtable pointer lifetime and vbase pointer (offset) > lifetime. Essentially, you can't use viable pointers or do vbase conversions > before they are set, and they are only set at a particular time. The > standard keeps it simple and expands to non-POD, but I'd argue that from a > QOI we should not make things that can work, not work. See below on QOI > issues.
I think we must distinguish what is "wrong" according to the standards we are implementing from what is "wrong" from a QoI point of view. My reasoning (for C++98, but the same is true for C++11) is based on 3.8/1: […] The lifetime of an object of type T ends when: -- if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or -- the storage which the object occupies is reused or released. Doing a placement-new on the storage occupied by 'a' is reusing its storage, therefore ending its lifetime. -- Gaby > > I can't quote it, since the limitation doesn't exist. I can quote the > language that allows & on an object, that you can then cast this to be of a > different type, and then dereference and use that type, if you want. I can > quote the object lifetime rules, that describe when it comes into existence, > and when it goes away. But, none of these are terribly surprising. If you > want to narrow done what part of the language you're interested in, I can > quote just that part. > > int a; > > a exists before the program runs, and exists till after the program is > finished running (See [basic.stc.static]). That's the lifetime of it. > During it's lifetime, you can use it in the ways the standard lets you. For > example, ++a;. In the below: > > void foo() { > char *cp = &a; > > [ … ] > } > > cp's lifetime is from the declaration of it, til the }. The character object > that cp points to has a lifetime. It's lifetime is from before the program > runs, til after the program finishes. (See [basic.life]) It can be used any > way that a lvalue character can be used. Since you can't use cp before it's > lifetime, to use this character object outside of the lifetime of cp, you'd > need another reference to it beyond just cp. Again, this isn't suppose to be > surprising. > > Now, we do have wording like: > > 15If a program attempts to access the stored value of an object through > an lvalue of other than one of the following types the behavior is > undefined48): > > and we do have latitude to do things that uses that as a basis, but, once one > ensures locking, say with atomics or volatile, to ensure the variable hits > memory, I will argue that we can't make as much use of that from a quality of > implementation viewpoint, despite the standard wording. Now, even without > volatile and locking, from a quality of implementation point of view, we > don't actually want to make full use of undefined. QOI still forces us to do > the right thing. undefined means, we get to kill the user. QOI means, even > though we can, we refrain from it, cause if we did, they would not like us. > > For the case of a int, and a placement new on that int, of an int. The > behavior is mandated by the standard to work. For a allocation function, > they are free to play games with persistence (or unexec a la emacs), with > allocated objects and this too has to work. This means they can alias, and > the standard says they can write this code and the standard mandates that it > works. > > Now, the user can use: > > @item malloc > @cindex @code{malloc} attribute > The @code{malloc} attribute is used to tell the compiler that a function > may be treated as if any non-@code{NULL} pointer it returns cannot > alias any other pointer valid when the function returns and that the memory > has undefined content. > This often improves optimization. > Standard functions with this property include @code{malloc} and > @code{calloc}. @code{realloc}-like functions do not have this > property as the memory pointed to does not have undefined content. > > on their allocation functions, if they want. And if they do, than what it > says is true, by definition, but not by standard. When this isn't true, the > user will refrain from using this attribute.