Prev: pros and cons of returning const ref to string instead of string by value
Next: pros and cons of returning const ref to string instead of string by value
From: Andy Venikov on 3 Dec 2009 07:53 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 3 Dec 2009 22:24 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 3 Dec 2009 22:33 > 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 3 Dec 2009 22:33 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 3 Dec 2009 23:07
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! ] |