0

I have a code that was written using old style c++, such as raw pointers like is shown below(code 1):

class Thing { 
    private:
        int data;
        Thing* one;
        Thing* second;
        Thing* previous;
    public:
        Thing():one(0), second(0), previous(0) {}
        // Here is my point of focus
        ~Thing() {
            delete one;
            delete second;
            delete previous;
        }
};

class Container {
    private:
        Thing* thing_ptr;
    public:
        Container() : thing_ptr(new Thing()) {}
        void make_empty {
        /*
            Some algorithm for manually destroying the whole structure.
        */
        }
        ~Container() {
            delete thing_ptr;
        }
};

My aim is to use smart pointers instead of raw pointers and do something like this (code 2):

class Thing { 
    private:
        int data;
        std::shared_ptr<Thing> one;
        std::shared_ptr<Thing> second;
        std::shared_ptr<Thing> previous;
    public:
        Thing() : one(nullptr), 
                  second(nullptr), 
                  previous(nullptr) {}

        // Here is my point of focus
        ~Thing() {
        // Do some stuff
        }
};

class Container {
    private:
        std::shared_ptr<Thing> thing_ptr;
    public:
        Container(): thing_ptr(nullptr) {}
        void make_empty {
        /*
            Some recursive algorithm for manually destroying the whole structure.
        */
        }
        /* Some other functions */
        ~Container() {
            // Do some stuff
        }
};

Case 1. How the compiler can delete the pointers that are holding in shared pointers if I will not provide the appropriate destructors? And will the procedure of deletion contain any destructor call from my classes?

Case 2. If there is no explicitly defined destructors and there are some other shared_ptr member variable that holds an object of class Field in class Thing like this:

class Field {...}

class Thing { 
    private:
        int data;
        std::shared_ptr<Field> field;
        std::shared_ptr<Thing> one;
        std::shared_ptr<Thing> second;
        std::shared_ptr<Thing> previous;
    public:
        Thing() : field(nullptr)
                  one(nullptr), 
                  second(nullptr), 
                  previous(nullptr) {}

        // Here is my point of focus
        ~Thing() {
            // Do some stuff
        }
};

Will the Field's destructor be invoked? If no then how compiler decides how to delete the stuff properly? Are there drawbacks?

std_name
  • 3
  • 2
  • 1
    If you don't provide a destructor then a defaulted one is generated which will just go on to destroy the data members – M.M May 23 '19 at 23:45
  • M.M - So destroying in that way have any drawbacks? – std_name May 23 '19 at 23:47
  • 2
    As a sidenote, `std::shared_ptr` has specific semantics and usage, `std::unique_ptr` should be preferred unless you need to share ownership (which is not the case usually with member variables in 90% of the situations, if you have a proper design). – Jack May 23 '19 at 23:48
  • Jack- There are some part of codes, where I'm making a temporary copies from that pointers, f.e. Thing* temp = thing_ptr whit unique_ptr it will transfer the ownership from thing_ptr to temp and thing_ptr will be useless, so having a unique_ptr wouldn't allow me to do such an assignments. – std_name May 24 '19 at 00:04
  • @std_name "_Thing* temp = thing_ptr_" `Thing* temp = thing_ptr.get();` – curiousguy Jun 01 '19 at 17:55

1 Answers1

1

The destructors of member variables are automatically invoked after the contents of your destructor. The constructors are invoked in the opposite order of construction.

Also, you should be using unique_ptr not shared_ptr. shared_ptr does reference counting which you almost certainly do not need.

user2445507
  • 443
  • 3
  • 13
  • The default generated destructors will be called in the case of when there are no explicitly defined ones or deletion will be done in some other way? – std_name May 23 '19 at 23:44
  • This has nothing to do with default destructors. unique_ptr (and shared_ptr) has a destructor defined that will delete the held pointer (if it exists). This destructor will be called no matter what you put in your Thing or Container destructors. – user2445507 May 23 '19 at 23:50
  • You should remove make_empty. It's not needed if you use smart pointers. They will auto-delete themselves for you. – user2445507 May 23 '19 at 23:50
  • user2445507 - The aim of having make_empty() function is to have a chance to delete the whole structure not only when the object goes out of scope but instead when it is needed by purpose of code. That's why this function was implemented. – std_name May 23 '19 at 23:56
  • user2445507- There are some part of codes, where I'm making a temporary copies from that pointers, f.e. Thing* temp = thing_ptr whit unique_ptr it will transfer the ownership from thing_ptr to temp and thing_ptr will be useless, so having a unique_ptr wouldn't allow me to do such an assignments. – std_name May 24 '19 at 00:03
  • Instead of make_empty(), why not just re-assign the object? – user2445507 May 24 '19 at 00:15
  • Why are you transferring unique_ptr ownership to other objects? You can just get the pointer. – user2445507 May 24 '19 at 00:16