c++object-destruction

Destructor calls on objects never constructed before


I have the following code.

class Wave {

int m_length;
data_type * m_data;

public:

    Wave(){
        blah...blah...blah
        m_data = NULL;
        m_length = 0;
        cout << "Wave " << this << " created on " << m_data << " with m_length " <<  m_length << endl;
    }

    Wave(int len, data_type data){
        blah...blah...blah
        if (len) {
            m_length = len;
            m_data = new data_type [m_length];
        } else {
            m_length = 0;
            m_data = NULL;
        }
        cout << "Wave " << this << " created on " << m_data << " with m_length " <<  m_length << endl;
    }



    ~Wave() 
    {
    cout << "Wave " << this << " destructor  on " << m_data << " started ";
        if (m_length) delete[] m_data;
    cout << "and finished " << endl;
    };        





    Wave & operator+= (const Wave wave){
    cout << __FUNCTION__ << ":" << __LINE__ << " m_length " << m_length << endl;
    if (NULL != m_data){
        data_type * tBuf = new data_type [m_length + wave.Length()];
        copy (wave.begin(),wave.end(), copy (begin(),end(),iterator(tBuf)));
        cout << "Wave " << this << " data on " << m_data << " moved onto " << tBuf;
        delete[] m_data;
        m_data = tBuf;
        cout << " and deleted" << endl;
    } else {
        m_data = new data_type [wave.Length()];
        copy (wave.begin(), wave.end(), begin());
        cout << "Wave " << this << " data created on " << m_data << " of length " <<  wave.Length() << endl;
    }
    m_length += wave.Length();
    cout << __FUNCTION__ << ":" << __LINE__ << " m_length " << m_length << endl;
    return *this;
    };

}


main(){

blah..blah..blah

Wave sample;

for (......) {

    cout << pulseNum << "-th High part: " << pulse->first << endl;
    Wave tSample(x,y);
    blah.blah.blah

    sample += tSample;

    cout << endl << pulseNum++ << "-th Low part: " << pulse->second << endl;
    tSample = Wave(a,b);
    blah.blah.blah

    sample += tSample;
}

}

Below is a log of execution this code

Wave 0x28fe34 created on 0 with m_length 0
0-th High part: 220
Wave 0x28fe54 created on 0xc60f00 with m_length 207
operator+=:211 m_length 0
Wave 0x28fe34 data created on 0xc610a8 of length 207
operator+=:230 m_length 207
Wave 0x28fe9c destructor  on 0xc60f00 started and finished

0-th Low part: 320
Wave 0x28febc created on 0xc61250 with m_length 301
Wave 0x28febc destructor  on 0xc61250 started and finished
operator+=:211 m_length 207
Wave 0x28fe34 data on 0xc610a8 moved to 0xc61250 and deleted 
operator+=:230 m_length 508
Wave 0x28fee0 destructor  on 0xc61250 started and finished

Wave 0x28fe54 destructor  on 0xc61250 started and finished

Most strange thing for me is that destructor is called more times than contructor. Moreover, it was called for objects never costructed before but for the same data address.
How can it be?


Solution

  • If you want to simplify your code, just define a std::vector<data_type> m_data data member, instead of using raw pointers (data_type * m_data).

    In this way, the compiler will automatically generate proper copy constructor, copy operator= (and also move semantics for C++11-compliant compilers) and destructor for you class (the automatically generated copy constructor, copy operator= and destructor will operate member-wise, e.g. the automatically generated copy constructor will call copy constructors for each data members of your class).

    To allocate data, instead of:

    m_data = new data_type [m_length];
    

    use:

    m_data.resize(m_length);
    

    You can also get rid of m_length data member, since the std::vector knows its own size (you can access it via std::vector::size() method).

    Note that std::vector stores all its elements in a single continuous memory area (like new[]); you can access the beginning of that area using &m_data[0].