Multiple destructors called in relation of vector<> structure

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • iammilind
    New Member
    • Sep 2006
    • 14

    Multiple destructors called in relation of vector<> structure

    I am not able to understand why the 2nd ~Test() is called with different 'this' but the same string value ??
    Also why does it give error, if I want to declare Test::Str as a const string member ??

    Code:
    =======================================================
    struct Test{
      string Str;  [B]// Gives error if, you declare const string ![/B]
      Test(const string s) : Str(s) { cout<<Str<<"  Test() "<<this<<endl; }
     ~Test()                               { cout<<Str<<" ~Test() "<<this<<endl; }
    };
    
    struct TestWrapper{
      vector<Test> vObj;
      TestWrapper(const string s) {  vObj.push_back(s); }
     ~TestWrapper() { }
    };
    
    int main ()
    {
      TestWrapper obj("HELLO");
    }
    
    Output:
    ======
    HELLO  Test() 0x7fbffff700
    HELLO ~Test() 0x7fbffff700
    HELLO ~Test() 0x503040      [B]<------- Why ?[/B] 
    =======================================================
  • prasoonsaurav
    New Member
    • Dec 2009
    • 3

    #2
    string Str; // Gives error if, you declare const string !
    This is because std::vector requires its objects to be assignable. Declaring your string as "const" won't allow assignment operation to be performed on the vector object.

    I am not able to understand why the 2nd ~Test() is called with different 'this' but the same string value ??
    vObj.push_back( s);involves an implicit cast of s to Test. So what's actually happening is vObj.push_back( Test(s)); and the temporary object gets destroyed after it is copied into the vector.

    The object within the vector is constructed using a copy constructor (not the (const string s) constructor) which is why you don't see any constructor call corresponding to the destructor call.
    Try adding a copy constructor to your Test:
    Code:
    Test(const Test &obj)
    { 
        cout<<obj.Str<<" Test() "<<this<<endl;
        Str = obj.Str;
    }
    You'll see the copy constructor being called as well, this call happens at the time the object is being put in the vector. So we have two calls to constructors and two calls to destructor.

    Comment

    • Savage
      Recognized Expert Top Contributor
      • Feb 2007
      • 1759

      #3
      It's because of this:

      Code:
       TestWrapper(const string s) { vObj.push_back(s); }
      vObj is vector of type Test, but you are pushing a string into it, so implicit conversion happens because your Test has constructor which accepts string as a argument, therefore another Test instance is created and filled with text "HELLO" and thats the first line of your output.But the temporary that was created on stack inside the TestWrapper(con st string) has to be destroyed before the function ends, hence the first destructor call.

      The second call occurs when ~TestWrapper() gets called hence destroying the vObj, which in turns call destructors of its each member, there is one so another destructor is called and thats it.

      Comment

      • iammilind
        New Member
        • Sep 2006
        • 14

        #4
        Thanks for your replies to both.
        Is there any logical need to reconstruct the object. vector<> class is optimized, then why such multiple constructors are required ? Any idea.
        Because, if you don't have copy constructor or assignment operator, it might be hazardous like following:
        =============== =============== =============== ===
        struct Test{
        int *ptr;
        Test(int* const p) : ptr(p) { }
        ~Test( ) { delete ptr; } // Surely a double delete crash !!
        };

        int main( )
        {
        vector<Test> vObj; vObj.push_back( Test(new int));
        }

        =============== =============== =============== ===

        Comment

        • prasoonsaurav
          New Member
          • Dec 2009
          • 3

          #5
          Is there any logical need to reconstruct the object. vector<> class is optimized, then why such multiple constructors are required ?
          Frankly speaking there is no logical need to reconstruct the object but that's how C++ is designed to work.

          Because, if you don't have copy constructor or assignment operator, it might be hazardous like following:
          =============== =============== =============== ===
          struct Test{
          int *ptr;
          Test(int* const p) : ptr(p) { }
          ~Test( ) { delete ptr; } // Surely a double delete crash !!
          };

          int main( )
          {
          vector<Test> vObj; vObj.push_back( Test(new int));
          }
          In cases where dynamic memory allocation is performed even though compiler will provide a copy constructor and assignment operator, the memory must be allocated and deallocated manually(so you have to write your version of copy constructor and assignment operator considering dynamic memory allocation).

          Your above program invokes 'Undefined Behavior' because you are calling "delete ptr" but memory has not been allocated to 'ptr' by default in the copy constructor, thus crashing your application. So its better that you write a copy constructor yourself and allocate memory to 'ptr' inside it.

          Remember in your earlier case where you have used vector, you need not take care of the memory allocation and deallocation.

          Comment

          Working...