眼见的事实尚有假,背后的言语未必真。---谚语
当使用另一种方式去实现相同的任务时,过往的经验可以帮助你更快速的分析和实现。但有时候经验也会产生负面影响。
下面的一段例子表示当一个对象以值的形式包含另一个对象时,会自动调用另一个对象的析构函数。
#include <iostream> #include <cstring> using namespace std; class Tyre { char* brand; public: Tyre(Tyre &tyre) { cout<<"first construct."<<endl; this->brand = new char[strlen(tyre.brand)+1]; strcpy(this->brand,tyre.brand); } Tyre(char* _brand) { cout<<"Tyre("<<_brand<<")"<<endl; this->brand = new char[strlen(_brand)+1]; strcpy(this->brand,_brand); } ~Tyre() { cout<<"Tyre destruct:"<<brand<<endl; delete brand; } void print() { cout<<"This is "<<brand<<" Tyre."<<endl; } }; class Car { char* name; Tyre tyre2; public: Car(char* name,Tyre tyre):tyre2(tyre) { this->name = new char[strlen(name)+1]; strcpy(this->name,name); tyre2.print(); } ~Car() { cout<<"Car destructor:only delete name"<<endl; delete name; } void print() { cout<<"Car :"; this->tyre2.print(); } }; int main() { Tyre tyre1("g"); Car theCar("lexus",tyre1); theCar.print(); return 0; }编译:gcc -o leak main2.cpp -lstdc++
D:\workspace\C++\memory_leak\leak2>leak Tyre(g) first construct. first construct. This is g Tyre. Tyre destruct:g Car :This is g Tyre. Car destructor:only delete name Tyre destruct:g Tyre destruct:g
以引用的方式也一样自动调用其析构:
// #include <iostream> #include <cstring> using namespace std; class Tyre { char* brand; public: Tyre(char* _brand); ~Tyre(); void print(); }; Tyre::Tyre(char* _brand) { cout<<"Tyre("<<_brand<<")"<<endl; this->brand = new char[strlen(_brand)+1]; strcpy(this->brand,_brand); } Tyre::~Tyre() { cout<<"Tyre destruct:"<<brand<<endl; delete brand; } void Tyre::print() { cout<<"This is "<<brand<<" Tyre."<<endl; } class Car { char* name; Tyre& tyre2; public: Car(char* name,Tyre& tyre); ~Car(); void print(); }; Car::Car(char* name,Tyre& tyre):tyre2(tyre) { this->name = new char[strlen(name)+1]; strcpy(this->name,name); tyre2.print(); } Car::~Car() { cout<<"Car destructor:only delete name"<<endl; delete name; } void Car::print() { cout<<"Car :"; this->tyre2.print(); } int main() { Tyre tyre1("g"); Car theCar("lexus",tyre1); theCar.print(); return 0; }编译运行结果:
D:\workspace\C++\memory_leak\leak2>leak Tyre(g) This is g Tyre. Car :This is g Tyre. Car destructor:only delete name Tyre destruct:g而当包含对象的指针时,就不会像之前那样自动调用析构了,必须要像以前的规则,new和delete要成对出现:
// #include <iostream> #include <cstring> using namespace std; class Tyre { char* brand; public: Tyre(char* _brand); ~Tyre(); void print(); }; Tyre::Tyre(char* _brand) { cout<<"Tyre("<<_brand<<")"<<endl; this->brand = new char[strlen(_brand)+1]; strcpy(this->brand,_brand); } Tyre::~Tyre() { cout<<"Tyre destruct:"<<brand<<endl; delete brand; } void Tyre::print() { cout<<"This is "<<brand<<" Tyre."<<endl; } class Car { char* name; Tyre* tyre; public: Car(char* name,char* _tyre); ~Car(); void print(); }; Car::Car(char* name,char* _tyre) { this->name = new char[strlen(name)+1]; strcpy(this->name,name); tyre = new Tyre(_tyre); } Car::~Car() { cout<<"Car destructor:only delete name"<<endl; delete name; // delete tyre;//Do not forget. } void Car::print() { cout<<"Car :"; tyre->print(); } int main() { Car car1("benz","goodyear"); car1.print(); Car car2("bmw","michelin"); car2.print(); Car *car3 = new Car("audi","continental"); car3->print(); delete car3; return 0; }运行结果如下:
D:\workspace\C++\memory_leak\leak2>leak Tyre(goodyear) Car :This is goodyear Tyre. Tyre(michelin) Car :This is michelin Tyre. Tyre(continental) Car :This is continental Tyre. Car destructor:only delete name Car destructor:only delete name Car destructor:only delete name有三个Tyre没有释放内存,Car::~Car中解开注释,编译运行如下:
D:\workspace\C++\memory_leak\leak2>leak Tyre(goodyear) Car :This is goodyear Tyre. Tyre(michelin) Car :This is michelin Tyre. Tyre(continental) Car :This is continental Tyre. Car destructor:only delete name Tyre destruct:continental Car destructor:only delete name Tyre destruct:michelin Car destructor:only delete name Tyre destruct:goodyear