C++: delete with placement parameter [duplicate] - c++

Why C++ hasn't placement delete that directly corresponds to the placement new, i.e. calls the destructor and calls appropriate placement delete operator?
For example:
MyType *p = new(arena) MyType;
...
//current technique
p->~MyType();
operator delete(p, arena);
//proposed technique
delete(arena) p;

operator delete is unique in being a non-member or static member function that is dynamically dispatched. A type with a virtual destructor performs the call to its own delete from the most derived destructor.
struct abc {
virtual ~abc() = 0;
};
struct d : abc {
operator delete() { std::cout << "goodbye\n"; }
};
int main() {
abc *p = new d;
delete p;
}
(Run this example.)
For this to work with placement delete, the destructor would have to somehow pass the additional arguments to operator delete.
Solution 1: Pass the arguments through the virtual function. This requires a separate virtual destructor for every static member and global operator delete overload with different arguments.
Solution 2: Let the virtual destructor return a function pointer to the caller specifying what operator delete should be called. But if the destructor does lookup, this hits the same problem of requiring multiple virtual function definitions as #1. Some kind of abstract overload set would have to be created, which the caller would resolve.
You have a perfectly good point, and it would be a nice addition to the language. Retrofitting it into the existing semantics of delete is probably even possible, in theory. But most of the time we don't use the full functionality of delete and it suffices to use a pseudo-destructor call followed by something like arena.release(p).

Probably because there was syntax for explicitly calling a destructor without deallocation (exactly as in your question), but no syntax for explicit construction in raw memory?

Actually there is a placement delete which is called by the implementation for an object that was "allocated" using placement new if the constructor threw an exception.
From Wikipedia.
The placement delete functions are called from placement new expressions. In particular, they are called if the constructor of the object throws an exception. In such a circumstance, in order to ensure that the program does not incur a memory leak, the placement delete functions are called.

The whole point of placement new is to separate object creation from its memory management. So it makes no sense to tie it back during object destruction.
If memory for your objects is from heap and you want same lifetime for objects and their memory just use operator new and operator delete, maybe overriding them if you want any special behavior.
Placement new is good for example in vector, which keeps a large chunk of raw memory and creates and destroys object inside of it, but without releasing memory.

Related

Caveats and risks of calling a constructor and destructor like common methods?

There's a point in my program where the state of a certain object needs to be reset "to factory defaults". The task boils down to doing everything that is written in the destructor and constructor. I could delete and recreate the object - but can I instead just call the destructor and the constructor as normal objects? (in particular, I don't want to redistribute the updated pointer to the new instance as it lingers in copies in other places of the program).
MyClass {
public:
MyClass();
~MyClass();
...
}
void reinit(MyClass* instance)
{
instance->~MyClass();
instance->MyClass();
}
Can I do this? If so, are there any risks, caveats, things I need to remember?
If your assignment operator and constructor are written correctly, you should be able to implement this as:
void reinit(MyClass* instance)
{
*instance = MyClass();
}
If your assignment operator and constructor are not written correctly, fix them.
The caveat of implementing the re-initialisation as destruction followed by construction is that if the constructor fails and throws an exception, the object will be destructed twice without being constructed again between the first and second destruction (once by your manual destruction, and once by the automatic destruction that occurs when its owner goes out of scope). This has undefined behaviour.
You could use placement-new:
void reinit(MyClass* instance)
{
instance->~MyClass();
new(instance) MyClass();
}
All pointers remain valid.
Or as a member function:
void MyClass::reinit()
{
~MyClass();
new(this) MyClass();
}
This should be used carefully, see http://www.gotw.ca/gotw/023.htm, which is about implementing an assignement operator with this trick, but some points apply here too:
The constructor should not throw
MyClass should not be used as a base class
It interferes with RAII, (but this could be wanted)
Credit to Fred Larson.
Can I do this? If so, are there any risks, caveats, things I need to remember?
No you can't do this. Besides it's technically possible for the destructor call, it will be just undefined behavior.
Supposed you have implemented the assignment operator of your class correctly, you could just write:
void reinit(MyClass* instance) {
*instance = MyClass();
}
You should use a smart pointer and rely on move semantics to get the behavior you want.
auto classObj = std::make_unique<MyClass>();
This creates a wrapped pointer that handles the dynamic memory for you. Suppose you are ready to reset classObj to the factory defaults, all you need is:
classObj = std::make_unique<MyClass>();
This "move-assignment" operation will call the destructor of MyClass, and then reassign the classObj smart pointer to point to a newly constructed instance of MyClass. Lather, rinse, repeat as necessary. In other words, you don't need a reinit function. Then when classObj is destroyed, its memory is cleaned up.
instance->MyClass(); is illegal, you must get a compilation error.
instance->~MyClass(); is possible. This does one of two things:
Nothing, if MyClass has a trivial destructor
Runs the code in the destructor and ends the lifetime of the object, otherwise.
If you use an object after its lifetime is ended, you cause undefined behaviour.
It is rare to write instance->~MyClass(); unless you either created the object with placement new in the first place, or you are about to re-create the object with placement new.
In case you are unaware, placement new creates an object when you already have got storage allocated. For example this is legal:
{
std::string s("hello");
s.~basic_string();
new(&s) std::string("goodbye");
std::cout << s << '\n';
}
You can try using placement new expression
new (&instance) MyClass()

placement delete inside or outside destructor

I found the following code while reading placement new operator.
#include <iostream>
using namespace std;
class MyClass {
public:
// Placement new operator
void* operator new (size_t sz, void* v) {
cout << "Placement new invoked" << endl;
return v;
}
~MyClass() {
// Cleanup
}
};
int main()
{
// Create a buffer to store the object
int buffer[16];
cout << "Starting address of my buffer = " << &buffer << endl;
// Create the object. Use placement new
MyClass* obj = new (buffer) MyClass();
cout << "Location of my object = " << obj << endl;
// Don't delete object created with placement delete
// Call the destructor explicitly
obj->~MyClass();
}
I have few questions related to delete object which was created using placement new:
what is the clean up code needs to write in destructor in order to
free memory which was occupied obj in buffer memory.
is it not needed to define placement delete, if yes whether it needs to be inside destructor or outside destructor. If it is outside destructor how it will be called ?
Regular new does two things:
allocate memory for your object
construct your object in that memory space.
Placement new means you manage one of those and the other is managed as before.
You allocate / provide the memory for your object
Constructor is called in that memory space.
The reverse is delete of which the regular delete does the following:
Invoke the destructor of the object to clean-up
Free the memory that was allocated for it.
Note that they are done in reverse order for obvious reasons. You cannot free the memory that contains information about what needs to be cleaned up, unti you have finished using that memory. Whereas in construction you need to get hold of the memory first.
In what you call placement delete but is really the reverse of placement new, you need to perform the first step of destruction but not the second. Thus you call the object's destructor, and then you can free up the memory it uses / use it for something else.
The most common example of usage of placement new is in the implementation of std::vector which requires a contiguous buffer for its data, and which lets you reserve ahead (and if you don't it will probably do it for you). That part allocates the memory but does not construct the objects in it. Thus when they are constructed later, placement new is used.
what is the clean up code needs to write in destructor in order to free memory which was occupied obj in buffer memory
The destructor should just do what any destructor does: clean up any resources managed by the object. In this case, it doesn't manage any resources, so there's no need to do anything.
It shouldn't do anything special according to how the storage for the object itself was allocated. Managing that storage is the job for custom new and delete operators, when required.
is it not needed to define placement delete
No. Placement-new is used to construct an object in storage that you're managing yourself, and it's your responsibility to free that storage yourself. In this case, the storage is automatic, so it's automatically freed when the function exits.
Just as the allocator for placement-new does nothing (just returning the provided pointer to pre-allocated storage), so the corresponding deallocator would do nothing; and so it doesn't exist. You just need to destroy the object by calling its destructor directly, before disposing of the storage yourself.
The first thing to ask is: what are you trying to do? If you
define a placement operator new in a class, then that is the
only operator new which will be found when you write new
MyClass; you must always specify the extra arguments. And in
almost every case where you define a class specific operator
new, you should also define a class specific operator delete;
otherwise the global operator delete function will be called
when you write delete p, and that generally won't work.
If your goal is to systematically require separation of
allocation and initialization, and that is why you are defining
a member operator new, then you can provide a no-op operator
delete; if the constructor of the class can throw, then you'll
also want to provide a placement operator delete, since this is
what will be called if the constructor of a newed object exits
via an exception. There is no other way to call it, however.
When providing placement operator new, you must provide
a default operator delete which does the right thing; and when
providing several operator new for the same type, you need to
memorize somehow in each allocation which one was called, in
order to dispatch in the non-placement operator delete.
And by the way, just allocating a buffer as a local variable
does not guarantee sufficient alignment for anything but the
declared buffer type.
EDIT:
Just an example of what would be needed for the operator
delete functions (which must be members):
void operator delete( void* p ) {}
void operator delete( void* p, void* ) {}

Why is the delete operator required to be static?

I found this one question asking the same thing, however only the 'new' part was answered, so here goes again.
Why is the delete operator required to be static? Somehow it doesn't make sense. The new operator makes perfect sense, just like the constructor can't be virtual, neither can the new operator. However, the destructor can (and should) be virtual when you use inheritance, in order to allow destruction of objects being used (by way of polymorphism) as a base class.
I understand that, when the delete operator is called, the object has already been destroyed, so no 'this' exists. Yet it still makes sense, using the same reasoning as with virtual destructor, to have the delete operator match the new operator which created the object.
This is what I mean
class A
{
public:
virtual ~A() {}
};
class B : public A
{
public:
void* operator new (size_t sz);
void operator delete (void* ptr, size_t sz);
};
now if we do
A *ptr = new B();
delete ptr; // <-- fail
A's delete operator (default) should've been called, since it's static and it's not known (for anything but the trivial case here) at compile time which delete-operator is the correct one.
However, I made a small test program with the code above (just malloc/free in the new/delete operators, and print statement in delete), and compiled it using g++. Running it quite unexpectedly produced the output in B's delete operator.
My (real) question is this: Is there some implicit 'virtualness' to the delete operator? Is it only static in the no-this-pointer sense? Or is this just a g++ feature?
I started looking through the C++ specification, but I must admit, I was bit overwhelmed by it, so any help appreciated.
The answer in the language rules is really in 12.5 [class.free].
If you are deleting via a pointer to a base class then the destructor must be virtual or you get undefined behaviour. Otherwise, the implementation has to determine the dynamic type of the object being deleted.
12.5/4 says that when the delete isn't prefixed by :: then the deallocation function is determined by looking up delete in the context of the dynamic type's virtual destructor. This ensures virtual-like lookup, even though operator delete is always a static member function.
Raw allocation and deallocation happen conceptually outside of the object's lifetime so by the time the deallocation function is to be called, there is no longer an object to provide a virtual lookup mechanism but the lookup rules ensure that operator delete has a dynamic (virtual-lite!) lookup mechanism. This means that operator delete can sensibly be static without losing touch with the original object's dynamic type.
delete operator is for deallocating memory only, and memory is deallocated for the most derived class object as a whole - in one action - exactly the same way as with new operator it is allocated for the whole most-derived class object - the object of class passed as argument into new Class construct.
This is why when you do delete ptr; the delete operator is always called only once for the actual most-derived class of the object being deleted and the data on what class it is is deduced from either the vtable if the virtual destructor is present or the type of the pointer if there's no virtual destructor. That's why there'no implicit virtualness to the delete operator - all virtualness ends at the point of destructor call.

Why can I not call my class's constructor from an instance of that class in C++?

When can an object of a class call the destructor of that class, as if it's a regular function? Why can't it call the constructor of the same class, as one of its regular functions? Why does the compiler stops us from doing this?
For example:
class c
{
public:
void add() ;
c();
~c() ;
};
void main()
{
c objC ;
objC.add() ;
objC.~c() ; // this line compiles
objC.c() ; // compilation error
}
By definition, a constructor is only called once, when the object is created. If you have access to an object, then it must have been created, so you're not allowed to call the constructor again - this is the reason why explicit constructor calls are not allowed. Similarly, destructors must only be called once, when the object is destroyed. If this could always done automatically, then the language would also forbid explicit destructor calls.
However, in some circumstances, you might want precise control over memory management, and the ability to explicitly create and destroy objects within memory that you are managing. For this purpose, the language provides "placement new" to create an object at an arbitrary location, and explicit destructor calls to destroy objects created this way. An explicit constructor call wouldn't be useful, since you need to be able to specify the location of the new object - so you get "placement new" instead. An explicit destructor call is sufficient, so there's no need to invent some sort of matching "placement delete".
So: there is no valid use for explicit constructor calls, so they are not allowed. There is a valid use for explicit destructor calls, so they are (syntactically) allowed, with the rule that you must only ever use them on objects that won't otherwise be destroyed, i.e. objects created using "placement new", and in that case call them exactly once. Using them in any other way, like so many C++ errors, will compile but give undefined behaviour.
I think you can explicitly call the destructor if you make sure that the instance is replaced/recreated with a call to placement new:
class c
{
public:
void add() ;
c();
~c() ;
};
int main()
{
c objC ;
objC.add() ;
objC.~c() ; // this line compiles
new (&objC) c; // placement new invokes constructor for the given memory region
}
I've never seen this in practice, but logically it should work (unless c's constructor can throw, in which case, I imagine, hell could break loose during stack unwinding).
However, what you probably want is just assignment:
objC = c();
If the destructor has side-effects that you are interested in, implement assignment using the copy-and-swap idiom which gets the destructor invoked for the "left-hand" value.
A destructor must be called on an existing instance of a class - destructing the instance is what it does. A constructor creates a brand new instance of a class, so calling on an existing instance makes no sense.
This is similar to the way new and delete work:
int * p = new int; // call to new needs no existing instance
delete p; // call to delete requires existing instance
And note in your code, the object would be destroyed twice, once explicitly, and once implicitly at the end of its enclosing scope. You typically only explicitly call a destructor if you are doing something unusual, probably involving the use of placement new.
If you really need to do something like this, just create an additional function and call it from outside AND from the constructor itself, but let's see what happens when you do need such a call:
#include<new>
class A
{
//members
};
int main()
{
//allocate buffer
char* buffer = new char[sizeof(A)];
//construct A on that memory space
A * ptrToA = ::new (buffer) A();
//destroy the object
ptrToA->~A();
//deallocate the buffer
delete[] buffer;
}
One instance where you can find placement new usage is the standard
containers. The allocator takes in the responsibility to allocate the
buffer (allocate member) and the objects are constructed over that
buffer as they are added into the container. For example, when you do
reserve on vector object, it reserves the space for N objects meaning
allocates space for N objects but does not construct them. Then when
you do push_back etc, to add elements, they are created over that
buffer. Basically, it is a technique to reduce the overhead of
repeated calls to memory allocation function. And then when done, the
vector destructor would destroy the objects calling the destructor
explicitly for all objects in it and then call the deallocate()
function of the allocator to release the memory. Hope this helps.
Try this out :
obj.ClassName::ClassName() ; // it works in VC 6.0 compiler
Another way to think about the restriction is that a constructor is not just another function. Consider its definition: unlike other functions, it has no return value, and it may have an initializer list. That it just happens to have most of the syntax of a function is kind of a coincidence; it really exists only for the purpose of initializing a new instance of an object.
The constructor is there "c()" used with new, i.e.
c objC = new c();
If you want to call your constructor outside of the actual construction of the class instance then you either haven't understood the purpose of the constructor or are trying to put functionality in there that shouldn't be there.
You are asking about a particular style of syntax more than a language limitation. C++ allows you to call an object's constructor or destructor.
c objC;
objC.~c(); // force objC's destructor to run
new(&objC); // force objC's constructor to run
Why did the language designers not use this syntax instead?
c objC;
delete(&objC) c; // force objC's destructor to run
new(&objC) c; // force objC's constructor to run
Or why not:
c objC
objC.~c(); // force objC's destructor to run
objC.c(); // force objC's constructor to run
My opinion as to why they chose the syntax they did:
The first alternative is more flexible than the second. I can call the constructor / destructor on any address not just an instance. That flexibility is needed for allocation, but not for destruction. Also the first option's delete seems to be very dangerous once virtual destructors get in to the mess.
you can invoke the constructor of an instance's class using typeof:
class c
{
public:
void add() ;
c();
~c() ;
};
void main()
{
c objC ;
objC.add() ;
objC.~c() ; // this line compiles (but is a bad idea)
typeof objC otherObjC; // so does this.
}
This does not affect the value of the instance objC, but creates a new instance otherObjC using objC's class constructor.
Note: this may do something you don't expect if the static type is a baseclass of the dynamic type of the instance you have.
Who says you can't? You just have to know how.
void Foo::Bar() {
*this = Foo(); // Reset *this
}

Does a destructor always get called for a delete operator, even when it is overloaded?

I'm porting a bit of an old code from C to C++. The old code uses object-like semantics, and at one point separates object destruction from freeing the now-unused memory, with stuff happening in between:
Object_Destructor(Object *me) { free(me->member1), free(me->member2) }
ObjectManager_FreeObject(ObjectManager *me, Object *obj) { free(obj) }
Is the above functionality possible in C++ using the standard destructor (~Object) and a subsequent call to delete obj? Or, as I fear, doing that would call the destructor twice?
In the particular case, the operator delete of Object is overridden as well. Is the definition I've read elsewhere ("when operator delete is used, and the object has a destructor, the destructor is always called) correct in the overridden operator case?
The delete operator is used to free memory, it doesn't change whether the destructor is called or not. First the destructor is called, and only after that is the delete operator used to deallocate the memory.
In other words it's not possible to achieve the semantics you're aiming at with C++'s destructors and delete operators.
Sample:
#include <iostream>
#include <new>
using namespace std;
struct foo {
~foo() { cout << "destructor\n"; }
void operator delete(void* p) {
cout << "operator delete (not explicitly calling destructor)\n";
free(p);
cout << "After delete\n";
}
};
int main()
{
void *pv = malloc(sizeof(foo));
foo* pf = new (pv) foo; // use placement new
delete pf;
}
Output:
destructor
operator delete (not explicitly calling destructor)
After delete
Overloaded delete still calls destructor implicitly before it starts executing as opposed to placement delete (but placement delete is not supposed to be called directly).
So if you are going to "delete" object, do not destroy it in advance you will have destructor called twice. However explicit destruction is due if object was created with placement new (but in that case you do not destroy object using delete)
What sort of stuff happens between the destruction of the object and the freeing of the object's memory? If it has nothing to do with the object, then you should be able to delete the object where the destructor appears. If it does, well, I'd examine that very carefully, because it sounds like a bad idea.
If you have to reproduce the semantics, have a member function that releases all the resources, and use that instead of the destruct function. Make sure that function can be called more than once safely, and include it in the C++ destructor just to be sure.
I absolutely don't get why people say it's impossible.
Decoupling initialization from construction and zeroization (tm) from destruction is actually extremely simple.
class Clike
{
public:
Clike() : m_usable(true) {}
void clear(); // performs clean up then sets m_usable to false
~Clike() { if (m_usable) this->clear(); }
private:
bool m_usable;
// real variables
};
Then you can use it like so:
Clike* c = new Clike();
c->clear(); // performs cleanup
// stuff
delete c;
Actually, since destructors should never throw and do not return anything, it is not unusual at all that the cleanup and the destruction be separated so that the cleanup operation may report errors. Especially for complicated beasts like DB Connections etc...
While this is not a 'destructor' thing, it sure works, and so the C-code presented is actually perfectly reproducible without those fancy placement new etc...
You can separate destruction from deletion, but you probably don't really want to.
If you allocate the memory with new char[] or malloc, and then call placement new, then you can separate destruction (which you do by directly calling the destructor) from deletion (or free). But then you're no longer calling the class's overloaded operator delete, instead you're calling delete[] on the char array (or free).
If you call delete via a pointer to your class (the one you overloaded operator delete for), then that class's destructor will be called. So there is no way to separate them in the sense you ask for, of calling delete without the destructor.
No, it is not possible.
delete calls the destructor.
You will need to work out some kind of logic to ensure that Stuff happens in the right order.
Have a look at the std::allocators for the implementation. The answer is 'yes, they may be decoupled'. It's quite easy to do, it just not seen very often.
It sounds like you might want a placement new. On the other hand, it also sounds like your code is getting pretty hairy. It might be time for some heavy refactoring.
The destructor is coupled to delete and you can't call it twice because you can't explicitely call the destructor (or at least it is highly unusual and uncommon, I've never seen it).
However, just make object_destructor() a member function and call it explicitely (and usually it's good style to make it safe for being called twice. In your case however, calling twice is okay anyway, because calling free() with a NULL pointer is legal, so the alternate version of object_destructor is just to highlight how it could be done.
CLASS A {
object_destructor() { free(this->member1); free(this->member2); }
alternate_version_of_object_destructor() {
if (this->member1) { free(this->member1); this->member1= NULL; }
if (this->member2) { free(this->member2); this->member2= NULL; } }
~A() { /* do nothing or just call this->object_destructor() for safety */ }
}
foo() {
A *pa= new A;
pa->object_destructor(); /* member cleanup */
delete pa; /* free object memory */
}