Archived

This topic is now archived and is closed to further replies.

delete a void pointer

This topic is 5673 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am writing a linked list class CLinkedList. it''s nodes are base off of the CListNode class which has a void pointer to the data, like so:
  
class CListNode
{
  public:
    ...
  private:
    void* _data;
};

class CLinkedList
{
  public:
    ...
  private:
    CListNode* _list;
};
  
When I add nodes to the list, it works just fine. But when I try to delete the list, it won''t delete. I know this because my constructors and destructors in CListNode print to the console when called. Here is the destructor code for the CListNode class:
  
CListNode::~CListNode()
{
  if (_data)
  {
    delete _data;
    _data = NULL;
  }
}
  
Any help would be appreciated.

Share this post


Link to post
Share on other sites
Firstly, you are much better off using std::list than rolling your own.

Secondly, make sure your CLinkedList destructor destroys all the nodes :

  
CLinkedList::~CLinkedList
{
while( _list )
{
CListNode* next = _list->next;
delete _list;
_list = next;
}
}


Thirdly, if you use CListNode as a base class, make sure its destructor is virtual (otherwise the destructor called is determined by the static type of the pointer, not the dynamic type of the object).

Fourthly, deleteing void pointers never calls a destructor. To (roughly) quote SabreMan quoting the Standard "If you call delete on anything but a pointer to a base of your object, the results are undefined". Thus your data will not get cleaned up properly. (void* is for people who know what they''re doing).

Finally, have a nice day.



Documents [ GDNet | MSDN | STL | OpenGL | Formats | RTFM | Asking Smart Questions ]
C++ Stuff [ MinGW | Loki | SDL | Boost. | STLport | FLTK | ACCU Recommended Books ]

Share this post


Link to post
Share on other sites
Deleting void pointers is isn't legal as far as I know. You should look into templates.

Quick example:


  
template <class CListType> class CListNode
{
public:
...
private:
CListType* _data;
};

template <class CListType> class CLinkedList
{
public:
...
private:
CListNode<CListType> * _list;
};


/* somewhere else */
CLinkedList<int> list_of_integers;


[edited by - smart_idiot on June 5, 2002 12:55:11 PM]

Share this post


Link to post
Share on other sites
I encountered a problem with templates. When I wanted to save a temporary copy of the list (to loop thru it), I got a debug assertion message. I overloaded the ''='' operator, and it still didn''t work. I guess templates are the way I need to go...

Share this post


Link to post
Share on other sites
quote:
Original post by smart_idiot
Deleting void pointers is isn''t legal as far as I know.


Sure it is. If it points to an object with a dtor, the object''s dtors won''t be called, but the memory will be freed.
quote:

You should look into templates.


Agreed. Specifically, std::list.

Share this post


Link to post
Share on other sites
I''m going to have to disagree a little... while std::list is a terrific thing, I strongly believe that everyone needs to make their own working version of a linked list at least once in their coding careers.

Otherwise, yes, use templates. Using void* as a data type is generally unnecessary unless you''re doing something unusual.

-fel

Share this post


Link to post
Share on other sites
I want to dig in and make a list class myself, w/o using stl (using templates). How would I overcome the assignment problem mentioned above? i.e.

  
CLinkedList<CType> type;
type.AddItem(new CType());

CLinkedList<CType> copy = type; // debug assertion error

Share this post


Link to post
Share on other sites

Look up the 'explicit' keyword in C++, and you'll probably discover that:


  
CLinkedList<CType> type;
CLinkedList<CType> copy = type;


is equivalent to:


  
CLinkedList<CType> type;
CLinkedList<CType> copy(type);


Notice that you're not actually assigning anything: you're initializing a new object. The type of constructor used to instantiate the second object is called a copy-constructor. By default, the compiler generates a copy-constructor that copies all members of the original object (like the default assignment operator).

In the above example, the constructor used to instantiate 'type' allocates memory, but the constructor used for 'copy' doesn't; it merely copies all members (pointers) of 'type'. So you end up with two objects that have members pointing at a single set of data. Also, problems arise when you try to free the memory in the destructor, because you're deallocating the same memory twice.

btw:

  
CLinkedList<CType> type;
CLinkedList<CType> copy;
copy = type;


This does call the assignment operator.

Here's an example to play around with:


  
template<typename T>
class type
{
public:
type()
{ p_ = new T; }
type(const type& t)
{ p_ = new T(*t.p_); }
~type()
{ delete p_; }

type& operator=(const type& t)
{
*p_ = *t.p_;
return *this;
}

private:
T* p_;
};

int main()
{
type<int> t1; // construct

type<int> t2 = t1; // copy construct

type<int> t3(t1); // copy construct

type<int> t4; // construct

t4 = t1; // assign

}



When you're allocating resources in a constructor you almost always need a copy-constructor and an assignment operator too. If necessary, make them both private to prevent copying.

[edited by - kvh on June 6, 2002 10:31:05 AM]

Share this post


Link to post
Share on other sites