1

I am implementing standart template tree structure, and I came across small problem.

Idea that each node will hold pointer to some data. Later in order to delete element correctly I need to know if its a single pointer or pointer to an array.

Inside of my tree->ReleaseMemory() method I have this code:

if (node->_data != NULL)    {

        switch (_destructionMethod){

        case  tree_delete:
            delete  node->_data; break;
        case  tree_deleteList:
            delete [] node->_data; break;
        case  tree_free:
            free(node->_data); break;

    }


}

where _destructionMethod has been set during initialisation of the node. Is there any way I can choose correct destructor without predefining it in special variable for it during initialisation ?

Thanks!

kirbo
  • 1,707
  • 5
  • 26
  • 32
  • I thinkg this is a good time for me to figure out how to work with smart pointers, optionally I will come back to object wrapping. Thanks – kirbo Mar 25 '11 at 23:25

5 Answers5

4

First basic:

delete is used when you allocate memory with new:

int *p = new int;
int *a = new int[10];
//...
delete p; 
delete []a; //note the difference!

free is used when you allocate memory with malloc:

int *p = (int*)malloc(sizeof(int) * 1);
int *a = (int*)malloc(sizeof(int) * 10);
//...
free(p);
free(a); //no difference!

Now your problem:

Is there any way I can choose correct destructor without predefining it in special variable for it during initialisation

Consider policy-based design. That means, write allocator that will encapsulate allocation and deallocation in a class and use that consistently in your code.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 3
    I'm pretty sure the questioner knows this, since he sets `_destructionMethod` at initialization. I rather think the question is looking to avoid the need for this stored value, it is not asking which value to store. – Steve Jessop Mar 25 '11 at 23:19
2

No, there is no portable way to find out what allocator a particular pointer originally came from.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
2

There's no way to interrogate a pointer to find out how it was allocated, but a common idiom is to give the allocated object itself responsibility for its own destruction. It looks like your object types are not all class types, though, so you would need to wrap them in order to do this. For example:

class destroyable_node
{
    virtual void destroy() = 0;
};

template <typename T> class object_node : public destroyable_node
{
private:
    T * value_;

public:
    // Presumes T is copy-constructable.
    object_node(T value) : value_( new T(value) ) {}

    operator T&() {return value_;}
    operator T const &() const {return value_;}

    void destroy() {delete value_;}
};

template<typename T> class array_node : public destroyable_node
{
private:
    T * value_;

public:
    array_node(T[] value)
        : value_( new T[ sizeof(value)/sizeof(T) ] )
    {
        std::copy(value, value + sizeof(value)/sizeof(T), value_);
    }

    operator T*() {return value_;}
    operator T const *() const {return value_;}

    void destroy() {delete[] value_;}
};

...and so on.

Jollymorphic
  • 3,510
  • 16
  • 16
1

Don't do this at all. Use a smart pointer, like shared_ptr from C++0x or Boost or if that is not an option, auto_ptr from C++. If you could have more than one object, consider using std::vector.

Manual resource management is messy and difficult to get right.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 1
    While this might be possible it might still be valid to use raw pointer/data depending on the situation. But if so - i dont think one should implement a Release unless you handle the allocation from the beginning. – stefan Mar 25 '11 at 23:11
  • And note the existence of `boost::checked_array_deleter` and `std::default_delete` in C++0x – Steve Jessop Mar 25 '11 at 23:25
  • And avoid using std::auto_ptr<> with STL containers: http://stackoverflow.com/questions/111478/why-is-it-wrong-to-use-stdauto-ptr-with-stl-containers – rturrado Mar 26 '11 at 00:28
0

Maybe a better design is to implement an abstract interface used by your container with three concrete subclasses that know what kind of thing they hold pointers to. Your container would simply call a destroy() method in the base class and let the derived classes worry about calling the correct destructor.

jbruni
  • 1,238
  • 8
  • 12