眼见的事实尚有假,背后的言语未必真。---谚语
当使用另一种方式去实现相同的任务时,过往的经验可以帮助你更快速的分析和实现。但有时候经验也会产生负面影响。
下面的一段例子表示当一个对象以值的形式包含另一个对象时,会自动调用另一个对象的析构函数。
#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
生活中不能缺少经验,但不要迷信经验。