TITLE: the placement delete operator PROBLEM: marnold@netcom.com (Matt Arnold) Will the new "placement deletes" be directly accessible or only called automatically in cases like exceptions in constructors? RESPONSE: clamage@eng.sun.com (Steve Clamage), 10 Dec 95 The placement-delete is called automatically by the compiler only in the case of a constructor exiting via an exception. There is no syntax corresponding to new (placement_args) T for placement-delete. One reason for that lack is the difficulty of finding a suitable syntax. (The obvious syntax leads to ambiguities.) In addition, the utility of a placement-delete syntax is questionable. It would mean that at the point of the delete the programmer would need to know which version of new was used to construct the object. The placement-delete is just a function, and you can call it explicitly. Example: void* operator new(size_t, int, char*); // placement new void operator delete(void*, int, char*); // corresponding delete ... T* p = new (5, "hello") T; ... p->~T(); // destroy the object operator delete(p, 5, "hello"); // recycle the storage If you know enough to be able to write delete (5, "hello") p; // or whatever the syntax would be then you can certainly write the above code. Having the compiler keep track of the the right version of placement delete to be called automatically seemed like too much to require. For example, here is an entire compilation unit: #include void junk(Base* p) { delete p; } Now suppose class Derived has placement new and delete member functions, and we write Base* p = new (args) Derived; ... junk(p); The code for function junk would have to work without knowing whether the object was allocated with a placement new, and if so, what version of delete to use and with what parameters. Every use of delete would require extra overhead even in programs that had no instances of placement new or delete at all. For constructors and exceptions the situation is different. On the one hand, the programmer does not have the necessary information available to know whether to call the placement delete. On the other hand, the compiler has all the information it needs at the point of the construction and can add the necessary code to be executed as part of the exception mechanism. No overhead for programs that don't use the feature. RESPONSE: kanze@lts.sel.alcatel.de (James Kanze), 10 Dec 95 > p->~T(); // destroy the object > operator delete(p, 5, "hello"); // recycle the storage I've said things like this in the past too, but for some reason, it just hit me that the last line above is illegal, or at least dubious. The function operator delete requires a pointer to void; the language rules require this to be the first byte of the actual object. The relationship between the first byte of the actual object and the actual byte referenced by the pointer depends on the *dynamic* type of the object. The dynamic type. After p->~T() has executed. So I think you should replace the last two lines with: void* tmp = p ; p->~T() ; operator delete( tmp , 5 , "hello" ) ; [ Below is a more detail on seeing if this really is a problem under any given implementation. Skip it if not interested. -adc ] I don't have a compiler which supports placement-delete on this machine, so I've done basically the same thing with normal new and delete. You're welcome to try the following code, both with and without -DCORRECT in the compiler invocation line. IMHO, without the -DCORRECT, you have undefined behavior, with, it should work. #include #include #include struct B1 { int b1 ; virtual ~B1() {} } ; struct B2 { int b2 ; virtual ~B2() {} } ; struct D : B1 , B2 { virtual ~D() { cout << "In D::~D()" << endl ; } } ; void* operator new( size_t n ) { void* p = malloc( n ) ; cout << "In op new, returning " << p << endl ; return p ; } void operator delete( void* p ) { cout << "In op delete, freeing " << p << endl ; cout << flush ; free( p ) ; } int main() { B2* p = new D ; cout << "p = " << (void*)( p ) << endl ; #ifdef CORRECT void* tmp = p ; p->~B2() ; operator delete( tmp ) ; #else p->~B2() ; operator delete( p ) ; #endif return 0 ; } The latest compiler I have here, g++ 2.6.3, core dumps in both cases, after outputting a different address in the delete than in the free. Given that the exact definition of the implicit cast to void has only been clarified recently, I don't think that the compiler should be criticized too harshly for not anticipating what the standards committee was going to decide.