From: Andy Venikov on
What's the rational for not having placement delete?

I know you can define your own placement operator delete, but it will
only be called in case a constructor throws an exception when placement
new is called. You can't call placement delete directly.

This limitation greatly impairs the use of custom allocators.

For example, if you want you allocations to come from a specific memory
region and you have a handle to that region you can: (assuming
regionAllocator is an object of a custom RegionAllocator class)

X * px = new (regionAllocator) X;


But you can't

delete (regionAllocator) px;

you can only

delete px;


That puts an unduly difficult requirement on (presumably custom)
operator delete to figure out where the memory came from. And no, it's
not always possible to embed that information with the returned memory.


The only rational I can think of is the ability to destroy any object by
just having a pointer to it, which would make generic destructors a bit
easy. But in my view this is a draconian requirement.


Thanks,
Andy.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Seungbeom Kim on
Andy Venikov wrote:
> What's the rational for not having placement delete?

It's answered in
<http://www2.research.att.com/~bs/bs_faq2.html#placement-delete>:

'The reason that there is no built-in "placement delete" to
match placement new is that there is no general way of assuring
that it would be used correctly.'

though I think "placement delete" could still have been possible:
we still have the dereference operator even though we have no general
way of assuring that the pointer points to a valid object.

> This limitation greatly impairs the use of custom allocators.
>
> For example, if you want you allocations to come from a specific memory
> region and you have a handle to that region you can: (assuming
> regionAllocator is an object of a custom RegionAllocator class)
>
> X * px = new (regionAllocator) X;
>
>
> But you can't
>
> delete (regionAllocator) px;
>
> you can only
>
> delete px;

As suggested in the FAQ above, the correct way would be

if (px) {
px->~X();
regionAllocator.deallocate(px);
}

--
Seungbeom Kim

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: restor on
> What's the rational for not having placement delete?

C++ has a placement delete it is just spelled differently: I believe
explicit destructor call. Consider an example:

void createAndDestroy( Class * obj )
{
new (obj) Class("obj1"); // ctor w/o allocation
obj->~Class(); // dtor w/o deallocation
}

I think the naming convention is confusing, as this question reoccurs
time and again. And it is the "placement new" that is confusing, as it
implies special (trivial) form of allocation. They probably should be
called "explicit constructor call" and "explicit destructor call".

Regards,
&rzej

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Thomas Richter on
Andy Venikov schrieb:

> What's the rational for not having placement delete?

Because it is too application specific as what it should do. A placement
new, in its original and intentional form, places an object in a
memory location reserved by some means outside of the control of the
operator new itself, which means that a placement delete cannot, by
symmetry, release the memory of which the new didn't know how it was
allocated. Instead, you would call the destructor of the object
directly, and then release the memory manually similar to the way how
you allocated the memory manually to place the object in.

> This limitation greatly impairs the use of custom allocators.

This is a quite different use of the operator new "with parameters".
Here, instead of using the parameter to indicate the memory region where
to allocate the object in - the original intent of the specs - you use
the parameter to specify a "memory pool" to allocate the object from.
Strictly speaking, this is not a "placement new" but a "new with
parameters".

> For example, if you want you allocations to come from a specific memory
> region and you have a handle to that region you can: (assuming
> regionAllocator is an object of a custom RegionAllocator class)
>
> X * px = new (regionAllocator) X;
>
>
> But you can't
>
> delete (regionAllocator) px;
>
> you can only
>
> delete px;

Which is usually sufficient. What you can do (or what I typically do) is
to store the memory pool you allocated the object from along with the
object itself, in the allocated memory. Then, operator delete locates
this memory pool and releases the memory itself in that pool.

One way of doing that would be to provide custom operator new's (with
parameters) and custom operator delete's for the classes you would like
to pool-allocate.

> That puts an unduly difficult requirement on (presumably custom)
> operator delete to figure out where the memory came from. And no, it's
> not always possible to embed that information with the returned memory.

Why not? Please provide more details. Always worked for me.

> The only rational I can think of is the ability to destroy any object by
> just having a pointer to it, which would make generic destructors a bit
> easy. But in my view this is a draconian requirement.

I would rather say that it is a historic accident, namely that operator
new with parameters is actually intended for something different than a
"memory pool" allocation, namely a "placement new". And in that
situation, you simply don't need a "placement delete" because you have
to always destroy the object manually - and releasing the memory is as
much out of the scope of operator delete as it was for the corresponding
placement new.

Thus, I would believe the intended (but unpractical) use of memory pools
would rather be:

mem = pool->Allocate(sizeof(Object))
object = new(mem) Object;

and, quite symmetric to the above:

object->~Object();
pool->Release(object);

instead of the (nicer to read)

object = new(pool) Object;
delete object;

So long,
Thomas

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Goran Pusic on
On Dec 4, 1:53 am, Andy Venikov <swojchelo...(a)gmail.com> wrote:
> What's the rational for not having placement delete?
>
> I know you can define your own placement operator delete, but it will
> only be called in case a constructor throws an exception when placement
> new is called. You can't call placement delete directly.

Yes. I think this is OK WRT the idea behind: if you use default
operator new, then if constructor throws, runtime knows how to free
allocated memory. When you overload operator new, though, it's your
job to react to that exception from constructor, because only you know
the meaning of your new.

But note that placement new is often used to construct the object from
existing already available memory, so delete ain't needed at all. I
guess that's why it's optional.

>
> This limitation greatly impairs the use of custom allocators.
>
> For example, if you want you allocations to come from a specific memory
> region and you have a handle to that region you can: (assuming
> regionAllocator is an object of a custom RegionAllocator class)
>
> X * px = new (regionAllocator) X;
>
> But you can't
>
> delete (regionAllocator) px;
>
> you can only
>
> delete px;
>
> That puts an unduly difficult requirement on (presumably custom)
> operator delete to figure out where the memory came from. And no, it's
> not always possible to embed that information with the returned memory.

Ahhh, but if you allocate instances of your class both from standard
heap and your own allocator, are these still the same class? If
nothing else, they are not the same WRT that particular detail that is
heap handling.

If that is the case, you could have variants of your class: base (with
actual functionality), one where you use default allocation and one
that comes from a pool. Then you pass reference to base around for
work, and call operator delete (compiler picks correct one for you)
when it's time to go.

You should note that operator new and delete must "reverse-match" ;-)
in functionality for a given class instance. Even if what you want to
do was possible, you would still have to keep track of how a
particular instance was instantiated so that you can call appropriate
delete version. And if that is so, you could just as well split your
instances in two actual classes and be done with it. In other words,
it seems that you don't gain much (if anything) with your idea.

Goran.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]