[c++]Why is my class destructor called twice? -
i have such code like,
#include <iostream> #include <string> using namespace std; class heart { private: int bpm; public: heart(int bpm) : bpm(bpm) {} int getbpm() { return bpm; } }; class kidney { private: double percentfunction; public: kidney() : percentfunction(0) {} kidney(double pf) : percentfunction(pf) {} double getpf() { return percentfunction; } }; class person { private: string fname, lname; int age; heart h; kidney* k; public: person(string fn, string ln, int age, int bpm, double kpf1, double kpf2) : fname(fn), lname(ln), age(age), h(bpm) { k = new kidney[2]; k[0] = kidney(kpf1); k[1] = kidney(kpf2); cout << fname << " " << lname << ", aged " << age << ". heart bpm : " << bpm << ". kidneys' percent function indices: " << k[0].getpf() << " , " << k[1].getpf() << '.' << endl; } ~person() { cout << "a person dying!" << endl; delete[] k; } }; int main() { person p = person("jack", "bowen", 24, 60, 0.99, 0.98); }
then run code, error(debug assertion failed!) pops up. , can see destructor called twice. if remove delete [] k;
in ~person, there no such pop-up error.
there dynamic allocation in person constructor:
k = new kidney[2]; k[0] = kidney(kpf1); k[1] = kidney(kpf2);
so think should delete k in destructor. question why destructor called twice , how solve error?
i using vs 2013.
thank you!
the issue following. in line
person p = person("jack", "bowen", 24, 60, 0.99, 0.98);
you copy-initializing p
, i.e. creating temporary copied person p;
. @ end, temporary person("jack", "bowen", 24, 60, 0.99, 0.98);
destroyed, kidney*
pointer dangling, because didn't implement copy constructor , copy shallow (i.e. pointer being copied, not object points to). , destructor called twice because first called when temporary ends life (at end of statement), again when person p
goes out of scope @ end of main()
.
anytime class has pointer, implement copy constructor , assignment operator. or better, use smart pointers std::shared_ptr
, or better, standard containers keep track of dynamic memory std::vector/std::list
etc.
quick , dirty fix code (but really, must implement copy constructor since you're going have other kinds of issues, e.g. when returning person
s function or when passing person
s value):
person p("jack", "bowen", 24, 60, 0.99, 0.98);
this avoids temporary , uses direct initialization.
ps: in g++
, compiling -weffc++
warns these issues,
warning: 'class person' has pointer data members [-weffc++] not override 'person(const person&)' [-weffc++] or 'operator=(const person&)' [-weffc++]
i not sure if such compiler flag exists vs though.
Comments
Post a Comment