destructors

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • cronusf@gmail.com

    #1

    destructors

    If you have:

    #include <iostream>

    using namespace std;

    class Base
    {
    public:
    ~Base()
    {
    cout << "~Base()" << endl;
    }

    int x;
    };

    class Derived : public Base
    {
    public:
    ~Derived()
    {
    cout << "~Derived() " << endl;
    }

    int y;
    int z;
    };

    int main()
    {
    Base* b = new Derived;
    delete b;
    }

    Only ~Base() is called, which is expected since it is not virtual.
    However, when delete is called, will it free the memory allocated for
    the variables y and z?
  • george.priv@gmail.com

    #2
    Re: destructors

    On Oct 15, 12:20 am, cron...@gmail.c om wrote:
    If you have:
    >
    #include <iostream>
    >
    using namespace std;
    >
     class Base
    {
    public:
        ~Base()
            {
                    cout << "~Base()" << endl;
            }
    >
        int x;
    >
    };
    >
    class Derived : public Base
    {
    public:
            ~Derived()
            {
                    cout << "~Derived() " << endl;
            }
    >
        int y;
        int z;
    >
    };
    >
    int main()
    {
        Base* b = new Derived;
        delete b;
    >
    }
    >
    Only ~Base() is called, which is expected since it is not virtual.
    However, when delete is called, will it free the memory allocated for
    the variables y and z?
    Yes

    Comment

    • Jerry

      #3
      Re: destructors

      On Oct 15, 12:24 pm, george.p...@gma il.com wrote:
      On Oct 15, 12:20 am, cron...@gmail.c om wrote:
      >
      >
      >
      >
      >
      If you have:
      >
      #include <iostream>
      >
      using namespace std;
      >
       class Base
      {
      public:
          ~Base()
              {
                      cout << "~Base()" << endl;
              }
      >
          int x;
      >
      };
      >
      class Derived : public Base
      {
      public:
              ~Derived()
              {
                      cout << "~Derived() " << endl;
              }
      >
          int y;
          int z;
      >
      };
      >
      int main()
      {
          Base* b = new Derived;
          delete b;
      >
      }
      >
      Only ~Base() is called, which is expected since it is not virtual.
      However, when delete is called, will it free the memory allocated for
      the variables y and z?
      >
      Yes
      I don't think so.
      To free y and z you must change ~Base() to virtual.

      Comment

      • Kai-Uwe Bux

        #4
        Re: destructors

        cronusf@gmail.c om wrote:
        If you have:
        >
        #include <iostream>
        >
        using namespace std;
        >
        class Base
        {
        public:
        ~Base()
        {
        cout << "~Base()" << endl;
        }
        >
        int x;
        };
        >
        class Derived : public Base
        {
        public:
        ~Derived()
        {
        cout << "~Derived() " << endl;
        }
        >
        int y;
        int z;
        };
        >
        int main()
        {
        Base* b = new Derived;
        delete b;
        }
        >
        Only ~Base() is called, which is expected since it is not virtual.
        However, when delete is called, will it free the memory allocated for
        the variables y and z?
        When delete is called you have undefined behavior as per [5.3.5/3]. In
        particular, all bets are off with respect to the memory of the variables y
        and z.


        Best

        Kai-Uwe Bux

        Comment

        • Salt_Peter

          #5
          Re: destructors

          On Oct 15, 12:20 am, cron...@gmail.c om wrote:
          If you have:
          >
          #include <iostream>
          >
          using namespace std;
          >
          class Base
          {
          public:
          ~Base()
          {
          cout << "~Base()" << endl;
          }
          >
          int x;
          >
          };
          >
          class Derived : public Base
          {
          public:
          ~Derived()
          {
          cout << "~Derived() " << endl;
          }
          >
          int y;
          int z;
          >
          };
          >
          int main()
          {
          Base* b = new Derived;
          delete b;
          >
          }
          >
          Only ~Base() is called, which is expected since it is not virtual.
          However, when delete is called, will it free the memory allocated for
          the variables y and z?
          No it won't.
          If you had used a smart pointer like boost::shared_p tr:

          #include "boost/shared_ptr.hpp"

          ....

          int main()
          {
          boost::shared_p tr< Base bsp(new Derived);
          // no delete needed
          }

          output:

          ~Derived()
          ~Base()

          Comment

          • Salt_Peter

            #6
            Re: destructors

            On Oct 15, 12:24 am, george.p...@gma il.com wrote:
            On Oct 15, 12:20 am, cron...@gmail.c om wrote:
            >
            >
            >
            If you have:
            >
            #include <iostream>
            >
            using namespace std;
            >
            class Base
            {
            public:
            ~Base()
            {
            cout << "~Base()" << endl;
            }
            >
            int x;
            >
            };
            >
            class Derived : public Base
            {
            public:
            ~Derived()
            {
            cout << "~Derived() " << endl;
            }
            >
            int y;
            int z;
            >
            };
            >
            int main()
            {
            Base* b = new Derived;
            delete b;
            >
            }
            >
            Only ~Base() is called, which is expected since it is not virtual.
            However, when delete is called, will it free the memory allocated for
            the variables y and z?
            >
            Yes
            No, absolutely not
            this test case proves it, ~Derived() is not invoked.

            Comment

            • Kai-Uwe Bux

              #7
              Re: destructors

              Salt_Peter wrote:
              On Oct 15, 12:24 am, george.p...@gma il.com wrote:
              >On Oct 15, 12:20 am, cron...@gmail.c om wrote:
              >>
              >>
              >>
              If you have:
              >>
              #include <iostream>
              >>
              using namespace std;
              >>
              class Base
              {
              public:
              ~Base()
              {
              cout << "~Base()" << endl;
              }
              >>
              int x;
              >>
              };
              >>
              class Derived : public Base
              {
              public:
              ~Derived()
              {
              cout << "~Derived() " << endl;
              }
              >>
              int y;
              int z;
              >>
              };
              >>
              int main()
              {
              Base* b = new Derived;
              delete b;
              >>
              }
              >>
              Only ~Base() is called, which is expected since it is not virtual.
              However, when delete is called, will it free the memory allocated for
              the variables y and z?
              >>
              >Yes
              >
              No, absolutely not
              this test case proves it, ~Derived() is not invoked.
              a) The destructor is not involved in freeing the memory for y and z. That
              would be an issue for the deallocation function invoked by delete.

              b) One has undefined behavior anyway [5.3.5/3] in the test case, so it
              proves nothing.


              Best

              Kai-Uwe Bux

              Comment

              • anon

                #8
                Re: destructors

                Kai-Uwe Bux wrote:
                cronusf@gmail.c om wrote:
                >
                >If you have:
                >>
                >#include <iostream>
                >>
                >using namespace std;
                >>
                > class Base
                >{
                >public:
                > ~Base()
                >{
                >cout << "~Base()" << endl;
                >}
                >>
                > int x;
                >};
                >>
                >class Derived : public Base
                >{
                >public:
                >~Derived()
                >{
                >cout << "~Derived() " << endl;
                >}
                >>
                > int y;
                > int z;
                >};
                >>
                >int main()
                >{
                > Base* b = new Derived;
                > delete b;
                >}
                >>
                >Only ~Base() is called, which is expected since it is not virtual.
                >However, when delete is called, will it free the memory allocated for
                >the variables y and z?
                >
                When delete is called you have undefined behavior as per [5.3.5/3]. In
                particular, all bets are off with respect to the memory of the variables y
                and z.
                >
                Sorry to hijack the tread, but is next example UB as well?

                // POD structure
                struct A
                {
                int a;
                };

                template< typename T >
                struct B : public T
                {
                int b;
                };

                int main()
                {
                B< A *inst = new B< A >;
                A &copy = *inst;

                inst->b = 2;
                copy.a = 3;

                delete inst;
                }

                Comment

                • Kai-Uwe Bux

                  #9
                  Re: destructors

                  anon wrote:
                  Kai-Uwe Bux wrote:
                  >cronusf@gmail.c om wrote:
                  >>
                  >>If you have:
                  >>>
                  >>#include <iostream>
                  >>>
                  >>using namespace std;
                  >>>
                  >> class Base
                  >>{
                  >>public:
                  >> ~Base()
                  >>{
                  >>cout << "~Base()" << endl;
                  >>}
                  >>>
                  >> int x;
                  >>};
                  >>>
                  >>class Derived : public Base
                  >>{
                  >>public:
                  >>~Derived()
                  >>{
                  >>cout << "~Derived() " << endl;
                  >>}
                  >>>
                  >> int y;
                  >> int z;
                  >>};
                  >>>
                  >>int main()
                  >>{
                  >> Base* b = new Derived;
                  >> delete b;
                  >>}
                  >>>
                  >>Only ~Base() is called, which is expected since it is not virtual.
                  >>However, when delete is called, will it free the memory allocated for
                  >>the variables y and z?
                  >>
                  >When delete is called you have undefined behavior as per [5.3.5/3]. In
                  >particular, all bets are off with respect to the memory of the variables
                  >y and z.
                  >>
                  >
                  Sorry to hijack the tread, but is next example UB as well?
                  >
                  // POD structure
                  struct A
                  {
                  int a;
                  };
                  >
                  template< typename T >
                  struct B : public T
                  {
                  int b;
                  };
                  >
                  int main()
                  {
                  B< A *inst = new B< A >;
                  A &copy = *inst;
                  >
                  inst->b = 2;
                  copy.a = 3;
                  >
                  delete inst;
                  }
                  No undefined behavior that I would see. However, with

                  A* inst = new B< A >;
                  ...
                  delete inst;

                  you would violate [5.3.5/3] as the static type and the dynamic type differ
                  but the base A does not have a virtual destructor.

                  BTW: that the types are POD is unrelated.


                  Best

                  Kai-Uwe Bux

                  Comment

                  • george.priv@gmail.com

                    #10
                    Re: destructors

                    On Oct 15, 3:14 am, Salt_Peter <pj_h...@yahoo. comwrote:
                    On Oct 15, 12:24 am, george.p...@gma il.com wrote:
                    >
                    >
                    >
                    On Oct 15, 12:20 am, cron...@gmail.c om wrote:
                    >
                    If you have:
                    >
                    #include <iostream>
                    >
                    using namespace std;
                    >
                     class Base
                    {
                    public:
                        ~Base()
                            {
                                    cout << "~Base()" << endl;
                            }
                    >
                        int x;
                    >
                    };
                    >
                    class Derived : public Base
                    {
                    public:
                            ~Derived()
                            {
                                    cout << "~Derived() " << endl;
                            }
                    >
                        int y;
                        int z;
                    >
                    };
                    >
                    int main()
                    {
                        Base* b = new Derived;
                        delete b;
                    >
                    }
                    >
                    Only ~Base() is called, which is expected since it is not virtual.
                    However, when delete is called, will it free the memory allocated for
                    the variables y and z?
                    >
                    Yes
                    >
                    No, absolutely not
                    this test case proves it, ~Derived() is not invoked.
                    Automatic members will be deallocated outside of the user-provided
                    destructor similar to allocating deallocating by malloc/free. If y, z
                    would be a pointers allocated within the lifetime of Derived object
                    and deallocated by Derived::~Deriv ed(), then you will get a memory
                    leak.

                    Regards, George

                    Comment

                    • Salt_Peter

                      #11
                      Re: destructors

                      On Oct 15, 8:59 am, george.p...@gma il.com wrote:
                      On Oct 15, 3:14 am, Salt_Peter <pj_h...@yahoo. comwrote:
                      >
                      >
                      >
                      On Oct 15, 12:24 am, george.p...@gma il.com wrote:
                      >
                      On Oct 15, 12:20 am, cron...@gmail.c om wrote:
                      >
                      If you have:
                      >
                      #include <iostream>
                      >
                      using namespace std;
                      >
                      class Base
                      {
                      public:
                      ~Base()
                      {
                      cout << "~Base()" << endl;
                      }
                      >
                      int x;
                      >
                      };
                      >
                      class Derived : public Base
                      {
                      public:
                      ~Derived()
                      {
                      cout << "~Derived() " << endl;
                      }
                      >
                      int y;
                      int z;
                      >
                      };
                      >
                      int main()
                      {
                      Base* b = new Derived;
                      delete b;
                      >
                      }
                      >
                      Only ~Base() is called, which is expected since it is not virtual.
                      However, when delete is called, will it free the memory allocated for
                      the variables y and z?
                      >
                      Yes
                      >
                      No, absolutely not
                      this test case proves it, ~Derived() is not invoked.
                      >
                      Automatic members will be deallocated outside of the user-provided
                      destructor similar to allocating deallocating by malloc/free. If y, z
                      would be a pointers allocated within the lifetime of Derived object
                      and deallocated by Derived::~Deriv ed(), then you will get a memory
                      leak.
                      >
                      Regards, George
                      The members are not automatic:

                      #include <iostream>

                      class Member
                      {
                      public:
                      ~Member()
                      {
                      std::cout << "~Member()" << std::endl;
                      }
                      };

                      class Base
                      {
                      Member m;
                      public:
                      ~Base()
                      {
                      std::cout << "~Base()" << std::endl;
                      }
                      };

                      class Derived : public Base
                      {
                      Member m;
                      public:
                      ~Derived()
                      {
                      std::cout << "~Derived() " << std::endl;
                      }
                      };

                      int main()
                      {
                      Base* p_b = new Derived;

                      delete p_b;
                      }

                      output:

                      ~Base()
                      ~Member()

                      With virtual ~dtor:

                      ~Derived()
                      ~Member()
                      ~Base()
                      ~Member()

                      Comment

                      • george.priv@gmail.com

                        #12
                        Re: destructors

                        On Oct 15, 10:14 am, Salt_Peter <pj_h...@yahoo. comwrote:
                        On Oct 15, 8:59 am, george.p...@gma il.com wrote:
                        >
                        >
                        >
                        On Oct 15, 3:14 am, Salt_Peter <pj_h...@yahoo. comwrote:
                        >
                        On Oct 15, 12:24 am, george.p...@gma il.com wrote:
                        >
                        On Oct 15, 12:20 am, cron...@gmail.c om wrote:
                        >
                        If you have:
                        >
                        #include <iostream>
                        >
                        using namespace std;
                        >
                         class Base
                        {
                        public:
                            ~Base()
                                {
                                        cout << "~Base()" << endl;
                                }
                        >
                            int x;
                        >
                        };
                        >
                        class Derived : public Base
                        {
                        public:
                                ~Derived()
                                {
                                        cout << "~Derived() " << endl;
                                }
                        >
                            int y;
                            int z;
                        >
                        };
                        >
                        int main()
                        {
                            Base* b = new Derived;
                            delete b;
                        >
                        }
                        >
                        Only ~Base() is called, which is expected since it is not virtual..
                        However, when delete is called, will it free the memory allocatedfor
                        the variables y and z?
                        >
                        Yes
                        >
                        No, absolutely not
                        this test case proves it, ~Derived() is not invoked.
                        >
                        Automatic members will be deallocated outside of the user-provided
                        destructor similar to allocating deallocating by malloc/free.  If y, z
                        would be a pointers allocated within the lifetime of Derived object
                        and deallocated by Derived::~Deriv ed(), then you will get a memory
                        leak.
                        >
                        Regards, George
                        >
                        The members are not automatic:
                        >
                        #include <iostream>
                        >
                        class Member
                        {
                        public:
                          ~Member()
                          {
                            std::cout << "~Member()" << std::endl;
                          }
                        >
                        };
                        >
                        class Base
                        {
                          Member m;
                        public:
                          ~Base()
                          {
                            std::cout << "~Base()" << std::endl;
                          }
                        >
                        };
                        >
                        class Derived : public Base
                        {
                          Member m;
                        public:
                          ~Derived()
                          {
                            std::cout << "~Derived() " << std::endl;
                          }
                        >
                        };
                        >
                        int main()
                        {
                          Base* p_b = new Derived;
                        >
                          delete p_b;
                        >
                        }
                        >
                        output:
                        >
                        ~Base()
                        ~Member()
                        >
                        With virtual ~dtor:
                        >
                        ~Derived()
                        ~Member()
                        ~Base()
                        ~Member()
                        Correct, in your example compiler has no idea that m needs destructor
                        to be called, but it's memory will be freed nonetheless even without
                        calling ~Member().

                        G.

                        Comment

                        Working...