472,135 Members | 1,214 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,135 software developers and data experts.

Overriding placement new correctly

Hi folks,

I am doing something Very Bad and Wrong (which I'll spare you the
details of) that requires overloading new for some specific classes.
So, for example:

class MyWeirdThingy
{
public:
...
static void* operator new(size_t size)
{
return my_weird_allocator(size);
}
};

This all works fine, there are no problems. However, I do also need to
use placement new for the same class in order to instantiate copies of
it contiguously in memory (as is typically the case with
implementations of std::vector, though I'm actually using my own
collection class).

If I attempt this with code like:

new (ptr) MyWeirdThingy(x)

to copy-construct an instance of the class to a particular address, gcc
wont compile the code because it fails to find an appropriate new
implementation. You can get around the error either by changing the
placement new to:

:: new (ptr) MyWeirdThingy(x)

or by adding a second overload within the class declaration of
MyWeirdThingy for placement new, e.g.:

static void* operator new(size_t size, void* p)
{
return p;
}

which is actually identical to the library version of placement ::new.
It all compiles and seems to work, but the copy construction doesn't
appear to be happening -- I seem to be seeing just default
construction. It is possible (very likely, actually!) that I have a
subtle bug somewhere, but I thought it worth asking whether it is
necessary to do anything beyond the above declaration when implementing
placement new -- since the same new gets called regardless of which
constructor is being invoked, surely you don't need to do anything
weird inside new in this case?

Confirmation that I'm not being stupid here would be appreciated.

Thank you in advance,
Sarah Thompson

PS: My reason for all this craziness is implementing a very unusual
memory model that supports something similar to transaction rollback
for a lattice of 'versions' -- it's part of an experimental model
checker.

Jan 3 '07 #1
1 11073
SarahT wrote:
I am doing something Very Bad and Wrong (which I'll spare you the
details of) that requires overloading new for some specific classes.
So, for example:

class MyWeirdThingy
{
public:
...
static void* operator new(size_t size)
{
return my_weird_allocator(size);
}
};

This all works fine, there are no problems. However, I do also need to
use placement new for the same class in order to instantiate copies of
it contiguously in memory (as is typically the case with
implementations of std::vector, though I'm actually using my own
collection class).
Two things:

"Every class-specific overload of void* operator new( /params/) must be
accompanied by a corresponding overload of void operator delete( void*,
/params/ ), where /params/ is a list of extra parameter types (of which
the first is always std::size_t).... The in-place form of operator
new...does not need a corresponding operator delete." --Sutter and
Alexandrescu's _C++ Coding Standards_, Item 45

"If you provide any class-specific new, provide all of the standard
forms (plain, in-place, and no-throw." --_C++ Coding Standards_, Item
46 (The ones you don't care about can just be forwarding functions to
the global versions or, if applicable, using declarations for the base
class's versions.)
If I attempt this with code like:

new (ptr) MyWeirdThingy(x)

to copy-construct an instance of the class to a particular address, gcc
wont compile the code because it fails to find an appropriate new
implementation. You can get around the error either by changing the
placement new to:

:: new (ptr) MyWeirdThingy(x)

or by adding a second overload within the class declaration of
MyWeirdThingy for placement new, e.g.:

static void* operator new(size_t size, void* p)
{
return p;
}

which is actually identical to the library version of placement ::new.
The problem is that defining a class-specific operator new hides all
the other signatures for operator new. If there is a base class
involved that implements new/delete, add a using declaration to the
derived class, or if not, you should just provide a forwarding function
to the global placement new:

static void* operator new(size_t size, void* p)
{
return ::operator new( size, p );
}
It all compiles and seems to work, but the copy construction doesn't
appear to be happening -- I seem to be seeing just default
construction. It is possible (very likely, actually!) that I have a
subtle bug somewhere, but I thought it worth asking whether it is
necessary to do anything beyond the above declaration when implementing
placement new -- since the same new gets called regardless of which
constructor is being invoked, surely you don't need to do anything
weird inside new in this case?
Apart from the above comments, it seems like you are on the right
track. You might want to read section 15.6 of _The C++ Programming
Language_ 3rd ed. by Stroustrup and the two items from _C++CS_
mentioned above. If you need more help, post a minimal but complete
sample that demonstrates the problem (cf.
http://www.parashift.com/c++-faq-lit....html#faq-5.8).

Cheers! --M

Jan 3 '07 #2

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by BDob | last post: by
23 posts views Thread by Giancarlo Niccolai | last post: by
20 posts views Thread by Ioannis Vranos | last post: by
8 posts views Thread by elviin | last post: by
5 posts views Thread by ma740988 | last post: by
5 posts views Thread by Lagarde Sébastien | last post: by
15 posts views Thread by LuB | last post: by
9 posts views Thread by karthikbalaguru | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.