overriding operator new and accessing placement new

M

Mark P

I have a class in which I've redefined operator new and operator delete.
For example:

class C {
....
void* operator new(size_t size) {do some stuff; return void*}
void operator delete(void *p) {do some stuff;}
}

Then I tried to use an STL container of C objects, say list<C>. This
produced a long compiler error, the gist of which went like:

no matching function for call to `C::eek:perator new(size_t, void*&)`
candidates are: static void* C::eek:perator new(size_t)

Am I right in thinking that the container list<C> tried to invoke
placement new for class C, using memory secured by its own allocator,
but that my definition of operator new has hidden all other definitions
of new and so no matching definition was found?

My seems-to-work solution was to define placement new for C as well and
have it simply call global placement new:

void* operator new(size_t size, void*& loc)
{return :):eek:perator new(size,loc));}

Is this the right way to deal with this? I know that the "do some
stuff" clause of my ordinary operator new won't be executed, but this is
OK in my case (that will be done by the allocator which calls placement
new).

Also, if an object is created by placement new, then does it always get
deleted by an explicit destructor call rather than by calling operator
delete?

Thanks for your help,
Mark
 
D

David White

Mark P said:
I have a class in which I've redefined operator new and operator delete.
For example:

class C {
...
void* operator new(size_t size) {do some stuff; return void*}
void operator delete(void *p) {do some stuff;}
}

Then I tried to use an STL container of C objects, say list<C>. This
produced a long compiler error, the gist of which went like:

no matching function for call to `C::eek:perator new(size_t, void*&)`
candidates are: static void* C::eek:perator new(size_t)

Am I right in thinking that the container list<C> tried to invoke
placement new for class C, using memory secured by its own allocator,
Probably.

but that my definition of operator new has hidden all other definitions
of new and so no matching definition was found?

Probably. The usual scoping rules would cause it to be hidden.
My seems-to-work solution was to define placement new for C as well and
have it simply call global placement new:

void* operator new(size_t size, void*& loc)
{return :):eek:perator new(size,loc));}

I thought it was usually: void* operator new(size_t size, void *p);
I haven't come across a reference version before, and it shouldn't be needed
for the usual straightforward placement new.
Is this the right way to deal with this? I know that the "do some
stuff" clause of my ordinary operator new won't be executed, but this is
OK in my case (that will be done by the allocator which calls placement
new).

Also, if an object is created by placement new, then does it always get
deleted by an explicit destructor call rather than by calling operator
delete?

It normally would be. The trouble is that operator delete() is unlikely to
be able to tell how the memory was allocated, and would have no option but
to assume that the memory should be freed in the usual manner, but this
might be a big mistake if placement new was used. Therefore whoever used
placement new should not use delete in most circumstances, and so an
explicit destructor call is needed.

DW
 
M

Mark P

David said:
I thought it was usually: void* operator new(size_t size, void *p);
I haven't come across a reference version before, and it shouldn't be needed
for the usual straightforward placement new.

I thought the reference to pointer was unusual but I don't have any C++
reference that is explicit about this, and that was the form that the
compiler error claimed to want. Any thoughts on where I can find the
official word on this?
It normally would be. The trouble is that operator delete() is unlikely to
be able to tell how the memory was allocated, and would have no option but
to assume that the memory should be freed in the usual manner, but this
might be a big mistake if placement new was used. Therefore whoever used
placement new should not use delete in most circumstances, and so an
explicit destructor call is needed.

OK, that was my thought. I'm thinking of an STL Allocator which, in the
example I've seen, uses placement new to construct an object and uses a
destructor call to destroy, handling allocate and deallocate separately.
Thanks much for the reply.
 
D

David White

Mark P said:
I thought the reference to pointer was unusual but I don't have any C++
reference that is explicit about this, and that was the form that the
compiler error claimed to want. Any thoughts on where I can find the
official word on this?

I haven't checked the standard, but I can find no mention of a reference
version in Stroustrup's TC++PL 3rd ed., so I would be very surprised if a
reference version is required. A reference doesn't really make sense because
you would only need it to change the address stored in the pointer, and
placement new would not normally do that. If I add placement new to class C
and try std::vector<C> on VS .NET 2003, which is a fairly modern compiler,
it won't even compile with void *& as the second parameter. It needs void *.

DW
 
M

Mark P

David said:
I haven't checked the standard, but I can find no mention of a reference
version in Stroustrup's TC++PL 3rd ed., so I would be very surprised if a
reference version is required. A reference doesn't really make sense because
you would only need it to change the address stored in the pointer, and
placement new would not normally do that. If I add placement new to class C
and try std::vector<C> on VS .NET 2003, which is a fairly modern compiler,
it won't even compile with void *& as the second parameter. It needs void *.

I believe you're right. The dinkumware reference for the standard <new>
header also indicates void*, not void*&.
 
G

grahamo

A little off topic but while we're at it, I recently saw that if you
use placement new to allocate an object, say;

char memory[sizeof(Fred)]; // Line #1
void* place = memory; // Line #2

Fred* f = new(place) Fred();


we must then call the following to de-allocate.


f->~Fred(); // Explicitly call the destructor for the placed object

Question:

Are we obliged to call the destructor this way simply because the
runtime has no way of knowing that the object was allocated with
placement new as opposed to "regular" new? Or are there other reasons?

thanks

Graham
 
J

James Dennett

grahamo said:
A little off topic but while we're at it, I recently saw that if you
use placement new to allocate an object, say;

char memory[sizeof(Fred)]; // Line #1
void* place = memory; // Line #2

Fred* f = new(place) Fred();


we must then call the following to de-allocate.


f->~Fred(); // Explicitly call the destructor for the placed object

Question:

Are we obliged to call the destructor this way simply because the
runtime has no way of knowing that the object was allocated with
placement new as opposed to "regular" new? Or are there other reasons?

thanks

Graham

That reason's good enough, no? How else would you propose
to destroy the Fred object constructed in place?

-- James
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top