Destroying a vector of classes

This is a discussion on Destroying a vector of classes within the C++ Programming forums, part of the General Programming Boards category; I'm taking a data structure and algorithm in C++ class where we are expected to know about and be able ...

  1. #1
    Not just a squid...
    Join Date
    Sep 2004
    Posts
    25

    Destroying a vector of classes

    I'm taking a data structure and algorithm in C++ class where we are expected to know about and be able to use vectors, a topic which my previous C++ class neglected to mention. From what little I know about vectors they will make my upcomming assignment much easier so I am going to give them a try. My problem is this: I have a class in which I was planning on putting a vector of structs, but I decided that it would probably more efficient to make it a vector of classes instead. Am I correct in assuming that when the vector is destroyed it will automatically call the destructors for each class it contains, or do I have to code this myself? Also, since I'm using a vector in my first class with no other dynamically allocated space in that class, do I even need a destructor for it? Here's an example of what I'm talking about:

    Code:
    class Class1
    {
       // Public Members  <- Do I need a destructor here?
       private:
          vector<Class2> theVector;  // When this is destroyed will it destroy all of the Class2's it contains?
          // More private members
    };
    
    class Class2
    {
       // Public Members <- I know I need a destructor here.
       private:
          char *aString;  // Space for this will be dynamically allocated.
          // More private members
    };
    One final question, would it be better if vector<Class2> was vector<*Class2>, and if so how would affect how everything is destroyed? I assume if I make this change Class1 would then need a destructor of its own.

    Thanks in advance.

  2. #2
    Registered User
    Join Date
    Aug 2001
    Posts
    244
    when the vector is destroyed the destructors of its elements are called
    that means:

    if your container elements are pointers though then nothing would be done.

    unfortunately i dont know if there you can pass your own clean up procedure to a vector - but one solution would be creating a wrapper class for pointers which destroy the object they are pointing to.

    Code:
    template <class T> Pointer {
      T* p;
    
      ~Pointer() { delete p; }
    };
    
    std::vector< Pointer<MyClass> >
    this pointer wrapper isnt really useful in that simple way - but it can be extended to a SmartPointer class - that is basically a wrapper of a pointer which additionaly has a reference count (how often that pointer is referenced)
    if the reference count reaches 0 then the object is assumed to be not used anywhere anymore and can thus be safely deleted.
    this is useful if objects are used in multiple containers - then reference counts are actually the only way to keep track on when to delete that object.
    signature under construction

  3. #3
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    >>more efficient to make it a vector of classes instead.
    Well, no - a class is the same thing as a struct, but with everything private by default instead of public

    >>Am I correct in assuming that when the vector is destroyed it will automatically call the destructors for each class it contains
    Yes, the destructor of each element will be called automatically.

    >>with no other dynamically allocated space in that class, do I even need a destructor for it?
    I suppose not, if the destructor doesn't do anything that won't be done automatically anyway (all destructors of member variables will be called automatically).

    would it be better if vector<Class2> was vector<*Class2>, and if so how would affect how everything is destroyed? I assume if I make this change Class1 would then need a destructor of its own.
    It may improve efficiency somewhat, because rather than making copies of each struct/class with loads of variables, you'll just copy the pointer (4 bytes usually). HOWEVER, this would mean that you need to define your own destructor that frees the dynamic memory for you. HOWEVER, if you have your destructor free dynamic memory, then you would not be able to pass your class by value to any container or function, etc. - otherwise the destructor would foul things up - unless you define your own copy constructor that performs a deep copy, which would kill nearly any performance gain you'd just made.

    Dynamic memory in structs/classes is an ugly can of worms that you might like to avoid if possible, unless the dynamic memory is wrapped in an object of another class that shields you from nasty side-effects. In this particular case, I don't see a need for dynamic memory - but the option's always open to you.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  4. #4
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Just saw this:
    but one solution would be creating a wrapper class for pointers which destroy the object they are pointing to.
    There is a smart pointer class that is part of the STL:
    std::auto_ptr<type>. However, it CANNOT be used in containers like std::vector etc., as is covered in detail here:
    http://www.gotw.ca/publications/usin...ffectively.htm
    For the same reason, you cannot use the class that Raven posted in containers either. However, as Raven has also suggested, reference counting will solve this problem - although that can get to be pretty convoluted. If you want to get an idea of how reference counting can be implemented, take a look at this thread.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  5. #5
    Registered User
    Join Date
    Aug 2001
    Posts
    244
    well i was refering to my own SmartPointer class and it is "smart" enough to work with containers (since reference counted).

    but true, my simple pointer wrapper example would run into the problems mentioned on the site.
    signature under construction

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,318
    You do not need a destructor for Class1 unless there are other private members that require one.

    You need a destructor for Class2 as you said, but you also need a copy constructor and copy assignment operator. Generally, if you need a destructor you will need the other two. In this case, you definitely need the copy methods because you will be storing instances of Class2 in a vector, and the vector does a lot of copying. Even if that wasn't the case, good design would tell you to create the copy constructor and assignment operator. The default one would not copy the dynamically allocated char *aString member correctly.

    Why aren't you using an std::string instead of a char*? That would have the same benefit as using the vector - automatic construction, copying, and destruction, and unless other member variables exist you wouldn't need the destructor for Class2 any more.

    You should probably use std::vector<Class2> instead of std::vector<Class2 *>. Only use the second version if you want to use polymorphism with Class2, or if you see that your code is too slow because it is copying around Class2 objects.

  7. #7
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Right, didn't realize there was a char* in there (dynamic memory, as you pointed out yourself in a comment!). If you want everything to work properly then, you have 2 options: Either implement reference counting and define copy constructors etc. until you die from it, or else change the char* to std::string as has been suggested, so that it will all be done for you. If you use std::string, then the default copy constructor/assignment operator/destructor should suffice.

    **EDIT**
    >>unless there are other private members that require one.
    Clarification: Unless there are other private members that require cleanup that won't happen automatically in their destructors.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can you Initialize all classes once with New?
    By peacerosetx in forum C++ Programming
    Replies: 12
    Last Post: 07-02-2008, 10:47 AM
  2. Multiple Inheritance - Size of Classes?
    By Zeusbwr in forum C++ Programming
    Replies: 10
    Last Post: 11-26-2004, 08:04 AM
  3. im extreamly new help
    By rigo305 in forum C++ Programming
    Replies: 27
    Last Post: 04-23-2004, 11:22 PM
  4. Prime Number Generator... Help !?!!
    By Halo in forum C++ Programming
    Replies: 9
    Last Post: 10-20-2003, 07:26 PM
  5. include question
    By Wanted420 in forum C++ Programming
    Replies: 8
    Last Post: 10-17-2003, 03:49 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21