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?
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]
.