Opened 8 years ago

Closed 7 years ago

Last modified 7 years ago

#554 closed enhancement (fixed)

Document using operator new and delete for implementing clone()

Reported by: olly Owned by: olly
Priority: normal Milestone: 1.2.9
Component: Documentation Version:
Severity: normal Keywords:
Cc: Blocked By:
Blocking: Operating System: All

Description (last modified by olly)

Methods like MatchSpy::clone() return an object which has to be deallocatable with delete. If you define operator new and operator delete for your subclass then you can actually allocate objects in your implementation of the clone() method as you want and then handle deallocation appropriately via operator delete. See the first comment for example code.

This might make it feasible to implement MatchSpy::clone() in the bindings.


Original summary and description:

Complement clone() method with destroy()

Currently methods like MatchSpy::clone() return an object which has to be deallocatable with delete. If we added a virtual method:

virtual void
MatchSpy::destroy()
{
    delete this;
}

Then instead of:

delete matchspy;

Xapian could use:

matchspy->destroy();

And then subclasses of MatchSpy could allocate themselves in other ways in clone() and provide the corresponding code to deallocate the object in destroy().

This might make it feasible to implement MatchSpy::clone() in the bindings.

Marking for 1.3.0 for now.

Change History (4)

comment:1 Changed 8 years ago by olly

Oh, actually the user can implement operator new and operator delete in their subclass, and that approach doesn't require an extra virtual method, or the (admittedly small) overhead of calling it for each object destroyed.

This code demonstrates that this works for the situation we'd have:

#include <iostream>

using namespace std;

class Base {
    int x;
  public:
    Base(int x_) : x(x_) { }
    virtual ~Base() { }
};

class Derived : public Base {
  public:
    Derived(int x_) : Base(x_) { }

    static void* operator new(size_t size) {
        cout << "Derived::new(" << size << ")" << endl;
        return ::operator new(size);
    }

    static void operator delete(void * p, size_t size) {
        cout << "Derived::delete(" << size << ")" << endl;
        ::operator delete(p);
    }
};

int main() {
    Base * o = new Derived(42);
    delete o;
}

This trick probably also opens the way to wrapping Xapian::Weight (#401).

comment:2 Changed 7 years ago by olly

  • Component changed from Library API to Documentation
  • Description modified (diff)
  • Status changed from new to assigned
  • Summary changed from Complement clone() method with destroy() to Document using operator new and delete for implementing clone()

So that means we need to document this technique somewhere appropriate (so updating summary and description), and link to this from the notes in the doxygen comments such as:

Note that the returned object will be deallocated by Xapian after use with "delete". It must therefore have been allocated with "new".

And then implement MatchSpy::clone() etc in the bindings.

comment:3 Changed 7 years ago by olly

  • Resolution set to fixed
  • Status changed from assigned to closed

Documented in r16326.

comment:4 Changed 7 years ago by olly

  • Milestone changed from 1.3.0 to 1.2.9

Backported for 1.2.9 in r16364.

Note: See TracTickets for help on using tickets.