Xuan Zhou
Xuan Zhou

Reputation: 31

Regarding destructor in an array of objects

I have a question regarding how the destructor is called. For example, I created the following foo class and supplied with copy constructor, destructor and overloaded the assignment operator. I created a dynamic array of this foo objects and used the operator "=" to assign individual element of the array. I am very confused, immediately after the assignment operation, the destructor is called and when I want to access the data in the newly assigned object, I got very confusing result.Any suggestions?

enter image description here

#include <iostream>

using namespace std;
bool debug = true;

class foo{
private:
    int n;


    void init(int _n);
public:

    int* arr; // just to make it accessible so that we can tract the contents;

    foo(int _n);
    foo(int* _a, int len);
    foo(const foo & rhs);
    foo & operator=(const foo & rhs);
    ~foo();
};


void foo::init(int _n = 0){
    n = _n;
    arr = new int[n];
    for(int i = 0; i != n; i++) arr[i] = 0;
}

foo::foo(int _n = 0){
    init(_n);
}

foo::foo(int*_a, int len){
    init(len);
    for(int i = 0; i< len; i++) arr[i] = _a[i];
}

foo::foo(const foo &rhs){
    operator = (rhs);
}

 foo& foo::operator= (const foo &rhs){
     if(debug) cout<<"\nassignment operator overloaded";
     if (this != &rhs){
         if(n != 0) {
            n = rhs.n;
            delete [] arr;
            arr = new int[n];
            for(int i = 0; i < n; i++) arr[i] = rhs.arr[i];
         }
     }
     return *this;
}

foo::~foo(){
    if (debug)cout << "\ndestructor called\n";
    delete []arr;
}

int main(){

    { // a explicit block to see when the destructor is called;
        foo* f = new foo[4];
        int n = 4;
        int a[] = {0,1,2,3};
        for(int i = 0; i < n;i++) {
            cout<<i;
            f[i] = foo(a, i);
            cout<<f[i].arr[i]<<"\n"; // result is some seemingly random number;
        }
    }

    system("PAUSE");
}*

Upvotes: 0

Views: 132

Answers (2)

user2249683
user2249683

Reputation:

A big no no! Delegating initialization of an uninitialized object to the assignment operator is a no good idea:

foo::foo(const foo &rhs){
    operator = (rhs);
}

Better is:

foo::foo(const foo &rhs)
:   n(rhs.n), arr(new int[n])
{
    // copy rhs.arr to arr
}

// Note: Passing by value:
foo& operator = (foo rhs) {
   std::swap(n, rhs.n);
   std::swap(arr, rhs.arr);
   return *this;
   // Note: The swapped rhs will do the cleanup in the destructor
}

You will end up with less coding and exception safety

Another issue is:

cout << f[i].arr[i] << "\n"

You are printing an undefined 'end' value (arr[i] == arr[n])

Upvotes: 1

juanchopanza
juanchopanza

Reputation: 227390

When you do this:

f[i] = foo(a, i);

a temporary foo object is created on the RHS of the assignment operator. It is then used to assign to the foo on the LHS of the operator. Then, it is destroyed, therefore its destructor is called.

The reason for the garbage values after the assignments is probably that n is 0 in all the foos in the array. Your assignment operator is broken. You may want to have a look at the copy and swap idiom.

Upvotes: 3

Related Questions