If the constructor throws an exception during a new call, the similarly declared delete with the same parameters will be called. For this reason, placement new and delete should always be declared in matching pairs.
In this case, the delete will have the same signature as the array delete and the compiler will not be able to choose between them.
Edited to add sample code and output.
Your code did not implement the global array placement new that is forbidden:
void * operator new( size_t bytes, size_t )
This program will illustrate how the global new and delete are called.
#include <stdint.h>
#include <malloc.h>
#include <iostream>
#include <stdexcept>
using namespace std;
struct A
{
int a;
A( void )
: a( 1 )
{
cout << __LINE__ << " : A::A()" << endl;
throw logic_error( "That is .. illogical" );
}
};
// Placement new with size_t parameter
void * operator new( size_t bytes, size_t )
{
cout << __LINE__ << " : void * A::operator new( size_t bytes = " << bytes << ", size_t )";
void *p = malloc( bytes );
cout << " -> " << p << endl;
return p;
}
// C++11 : Array placement delete with size_t parameter
// C++14 : Array delete
void operator delete( void *p, std::size_t n )
{
cout << __LINE__ << " : void A::operator delete( void *p = " << p << ", size_t n = " << n << " )" << endl;
if (p)
free( p );
}
// Non-array new
void * operator new( size_t bytes )
{
cout << __LINE__ << " : void * A::operator new( size_t bytes = " << bytes << " )";
void *p = malloc( bytes );
cout << " -> " << p << endl;
return p;
}
// Non-array delete
void operator delete( void *p ) noexcept
{
cout << __LINE__ << " : void A::operator delete( void *p = " << p << " )" << endl;
if (p)
free( p );
}
// Array new
void * operator new[]( size_t bytes )
{
cout << __LINE__ << " : void * A::operator new[]( size_t bytes = " << bytes << " )";
void *p = malloc( bytes );
cout << " -> " << p << endl;
return p;
}
// Array placement new with size_t parameter
void * operator new[]( size_t bytes, size_t n )
{
cout << __LINE__ << " : void * A::operator new[]( size_t bytes = " << bytes << ", size_t n = " << n << " )";
void *p = malloc( bytes );
cout << " -> " << p << endl;
return p;
}
// C++11 : Array placement delete with size_t parameter
// C++14 : Array delete
void operator delete[]( void *p, std::size_t n )
{
cout << __LINE__ << " : void A::operator delete[]( void *p = " << p << ", size_t n = " << n << " )" << endl;
if (p)
free( p );
}
int main( int, char ** )
{
A *p = nullptr;
#if 1
try
{
cout << __LINE__ << " : ===== Array placement new allocate with size_t parameter. =====" << endl;
p = new( (size_t)4 ) A[ 3 ];
cout << __LINE__ << " : ===== Array placement new succeeded. =====" << endl;
}
catch (...)
{
}
cout << __LINE__ << " : ===== Array placement delete. =====" << endl;
delete[] p;
p = nullptr;
#endif
try
{
cout << __LINE__ << " : ===== Array new. =====" << endl;
p = new A[ 3 ];
cout << __LINE__ << " : ===== Array new succeeded. =====" << endl;
}
catch (...)
{
}
cout << __LINE__ << " : ===== Array delete. =====" << endl;
delete[] p;
p = nullptr;
cout << __LINE__ << " : ===== Complete. =====" << endl;
return 0;
}
Compiling with clang 3.4.2 for C++11 gives this result:
$ clang++ --std=c++11 -o replace_new main.cpp && ./replace_new
88 : ===== Array placement new allocate with size_t parameter. =====
66 : void * A::operator new[]( size_t bytes = 12, size_t n = 4 ) -> 0x80048358
14 : A::A()
40 : void * A::operator new( size_t bytes = 33 ) -> 0x800483d8
76 : void A::operator delete[]( void *p = 0x80048358, size_t n = 4 )
49 : void A::operator delete( void *p = 0x800483d8 )
97 : ===== Array placement delete. =====
105 : ===== Array new. =====
57 : void * A::operator new[]( size_t bytes = 12 ) -> 0x80048358
14 : A::A()
40 : void * A::operator new( size_t bytes = 33 ) -> 0x800483d8
49 : void A::operator delete( void *p = 0x80048358 )
49 : void A::operator delete( void *p = 0x800483d8 )
114 : ===== Array delete. =====
118 : ===== Complete. =====
The allocation of 33 bytes is the exception. The exception and the array are both deleted with the same delete function.
Compiling with C++14 rules gives this result:
$ clang++ --std=c++1y -o replace_new main.cpp && ./replace_new
main.cpp:89:17: error: 'new' expression with placement arguments refers to non-placement 'operator delete'
p = new( (size_t)4 ) A[ 3 ];
^ ~~~~~~~~~
main.cpp:74:10: note: 'operator delete[]' declared here
void operator delete[]( void *p, std::size_t n )
^
1 error generated.
Disabling the invalid section and compiling with C++14 rules gives this result:
$ clang++ --std=c++1y -o replace_new main.cpp && ./replace_new
105 : ===== Array new. =====
57 : void * A::operator new[]( size_t bytes = 12 ) -> 0x80048358
14 : A::A()
40 : void * A::operator new( size_t bytes = 33 ) -> 0x800483d8
76 : void A::operator delete[]( void *p = 0x80048358, size_t n = 12 )
49 : void A::operator delete( void *p = 0x800483d8 )
114 : ===== Array delete. =====
118 : ===== Complete. =====
Notice that the array is now deleted with a different delete function. It is the same delete function at line 76 that deleted the array placement new when compiled as C++11.
void * operator new(std::size_t t, std::size_t)
is an overload of new[] or something else? - user2953119new[]
that you wrote is doing the same thing asnew
: you're only allocating one value instead of an array - meneldalnew[]
. I wrotenew
. - user2953119delete[]
is what you call afternew[]
right? I think I'm confused about this. But if it's just the placementnew
you're not supposed to allocate memory in it since the memory is already allocated, you're just supposed to construct the object. - meneldal