1

Here is two sample classes and the implementation of destructor for class Foo. Why is m_barvec1 implemented as the way it is in the destructor and what does vector<Bar *> m_barvec1 mean?

class Bar { 
public:
    Bar() : m_arr(new int[100]) {} 
    ~Bar();
    int m_x;
    std::list<int> m_list;
    int* m_arr; 
};

class Foo { 
public:
    Foo() : m_barvec3(new std::vector<Bar>()) {} 
    ~Foo();
    Bar m_bar; 
    std::vector<Bar *> m_barvec1; 
    std::vector<Bar> m_barvec2;
    std::vector<Bar> *m_barvec3;
};

Foo::~Foo() {
    for (size_t i = 0; i < m_barvec1.size(); i++) {
        delete m_barvec1[i];
    }
    delete m_barvec3;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
aurora
  • 67
  • 3
  • 1
    Good reading: [What is meant by Resource Acquisition is Initialization (RAII)?](https://stackoverflow.com/questions/2321511/what-is-meant-by-resource-acquisition-is-initialization-raii) and [What is ownership of resources or pointers?](https://stackoverflow.com/questions/49024982/what-is-ownership-of-resources-or-pointers) – user4581301 May 05 '22 at 19:07
  • 1
    And that leads to [What is The Rule of Three?](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). – user4581301 May 05 '22 at 19:08
  • 1
    The objects pointed to by the pointers are being deleted in the destructor. m_barvec1 holds pointers to Bar objects. m_barvec3 is deleted because it is a pointer to a std::vector – edtheprogrammerguy May 05 '22 at 19:08
  • 1
    Slight clarification: The pointers are not deleted. The objects pointed at are deleted. You do not have to delete when you have a pointer, you have to delete when you have ownership of the pointed-at object. – user4581301 May 05 '22 at 19:09
  • 1
    `vector m_barvec1` is a vector of pointers to objects of type `Bar`. When the `Foo` object is decallocated, the destructor is deleting each of the objects pointed to by that vector. Is that the correct behavior, or are those pointers owned by something else that wants to keep them allocated? This kind of dileman is why smart pointers exist. – Chris May 05 '22 at 19:12
  • Where did this code come from? Did you write it yourself? – Paul Sanders May 05 '22 at 19:35
  • 2
    A somewhat pedantic answer to the question in the title would be that it's impossible to say, because the code doesn't show where these pointers came from. The destructor **might** be correct if all of those pointers were created with `new`. – Pete Becker May 05 '22 at 20:36

1 Answers1

1

m_barvec1 is a std::vector object holding raw pointers to Bar objects. The Foo destructor is destroying every Bar object being pointed at by the std::vector. A better way to handle this is to use std::unique_ptr<Bar> or std::shared_ptr<Bar> instead of Bar* for the std::vector's element type, let std::unique_ptr/std::shared_ptr destroy the Bar objects automatically.

m_barvec2 is a std::vector object holding Bar objects. The std::vector's destructor will handle destroying the Bar objects, so there is no user code needed in Foo's destructor to handle this.

m_barvec3 is a pointer to a std::vector object that holds Bar objects. The Foo destructor is destroying the std::vector being pointed at, which in turn will destroy the Bar objects it holds. A better way to handle this is to use std::unique_ptr<std::vector<Bar>> instead of std::vector<Bar>* for the pointer, let std::unique_ptr destroy the std::vector automatically.

Using smart pointers for m_barvec1 and m_barvec3 would allow Foo's destructor to then be removed completely.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770