overriding operator new and accessing placement new

Discussion in 'C++' started by Mark P, Apr 25, 2005.

  1. Mark P

    Mark P Guest

    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
    Mark P, Apr 25, 2005
    #1
    1. Advertising

  2. Mark P

    David White Guest

    "Mark P" <> wrote in message
    news:FRXae.145$...
    > 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
    David White, Apr 26, 2005
    #2
    1. Advertising

  3. Mark P

    Mark P Guest

    David White wrote:
    > "Mark P" <> wrote in message
    > news:FRXae.145$...
    >
    >
    >>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.
    >
    >


    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?

    >>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.


    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.

    >
    > DW
    >
    >

    Thanks much for the reply.
    Mark P, Apr 26, 2005
    #3
  4. Mark P

    David White Guest

    "Mark P" <> wrote in message
    news:rNjbe.670$...
    > David White wrote:
    > > 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?


    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
    David White, Apr 26, 2005
    #4
  5. Mark P

    Mark P Guest

    David White wrote:
    >
    > 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*&.
    Mark P, Apr 26, 2005
    #5
  6. Mark P

    grahamo Guest

    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

    Mark P <> wrote in message news:<FRXae.145$>...
    > 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
    grahamo, Apr 26, 2005
    #6
  7. grahamo wrote:

    > 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
    James Dennett, Apr 27, 2005
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ioannis Vranos

    Placement operator new/delete question

    Ioannis Vranos, Oct 16, 2004, in forum: C++
    Replies:
    11
    Views:
    5,663
    Ioannis Vranos
    Oct 16, 2004
  2. Cheng Mo
    Replies:
    3
    Views:
    699
    Victor Bazarov
    Nov 19, 2004
  3. mangesh
    Replies:
    15
    Views:
    620
    mlimber
    Jun 30, 2006
  4. SarahT
    Replies:
    1
    Views:
    328
    mlimber
    Jan 3, 2007
  5. Lagarde Sébastien

    overriding placement new + memory management

    Lagarde Sébastien, May 4, 2007, in forum: C++
    Replies:
    5
    Views:
    537
    Lagarde Sébastien
    May 7, 2007
Loading...

Share This Page