C++ 析构函数
我使用的继承开发环境: Visual Studio 2010
下面我们来做一个例子,看看:
#include
#include
using namespace std; class NoName{ public: NoName():pstring(new std::string), i(0), d(0){} private: std::string * pstring; int i; double d; }; int main(){ return 0; }
像上面这个 NoName 类这样的设计,类里面有一个成员变量是指针(std::string *pstring) ,那么在构造函数里我们使用 new 创建了对象,并使用 pstring 来操作这个对象。那么在这个情况下,我们就必须设计一个析构函数。
析构函数是这样编写的:(可以在类的里面声明,定义写在类的外面,)
class NoName{ public: NoName():pstring(new std::string) , i(0), d(0){ cout << "构造函数被调用了!" << endl; } ~NoName();
NoName::~NoName(){ cout << "析构函数被调用了!" << endl; }
析构函数是这样写的: ~NoName() ,它与构造函数唯一的区别就是,前面都加了一个 ~ 符号。 析构函数都是没有参数的,也就是说:析构函数永远只能写一个。
按照 C++ 的要求,只要有 new 就要有相应的 delete 。这个 new 是在构造函数里 new 的,就是出生的时候。所以在死掉的时候,就是调用析构函数时,我们必须对指针进行 delete 操作。
我们来在main() 函数中创建一个 NoName 实例对象来 测试一下:
int main(){ NoName a; return 0; }
并且在 main() 函数的 } 这一行添加一个断点,如图所示:

运行输出:
构造函数被调用了! 析构函数被调用了!
在定义 a 对象的时候,调用了 NoName 类的构造函数,在main() 函数执行完的时候,就是执行完 return 0; 这句话后,main() 函数的执行域结束,所以就要杀掉 a 对象,所以这个时候会调用 NoName 类的析构函数。
那么,如果我们在 main() 函数中使用 new 关键字来创建一个 NoName 类的实例化对象,会出现什么样的运行效果呢?
main() 函数中的代码如下:
int main(){ NoName a; NoName *p = new NoName; return 0; }
运行输出:
构造函数被调用了! 构造函数被调用了! 析构函数被调用了!
这里使用 new 创建的对象,就必须要使用 delete 来释放它。 牢牢的记住:new 和 delete 是一对。正确的代码是下面这个样子的:
int main(){ NoName a; NoName *p = new NoName; delete p; return 0; }
运行输出:
构造函数被调用了! 构造函数被调用了! 析构函数被调用了! 析构函数被调用了!
赋值构造函数:
在赋值的时候,不是讲指针赋值过来,而是将指针对应指向的字符串赋值过来,这是最关键的一步。
因为我们写了析构函数,就必须要将赋值构造函数写上:
class NoName{ public: NoName():pstring(new std::string) , i(0), d(0){ cout << "构造函数被调用了!" << endl; } NoName(const NoName & other); ~NoName();
NoName::NoName(const NoName & other){ pstring = new std::string; *pstring = *(other.pstring); i = other.i; d = other.d; }
除了要写 赋值构造函数,还要写赋值操作符。
class NoName{ public: NoName():pstring(new std::string) , i(0), d(0){ cout << "构造函数被调用了!" << endl; } NoName(const NoName & other); ~NoName(); NoName& operator =(const NoName &rhs);
NoName& NoName::operator=(const NoName &rhs){ pstring = new std::string; *pstring = *(other.pstring); i = other.i; d = other.d; return *this; }
只要你写了析构函数,就必须要写 赋值构造函数 和 赋值运算符,这就是著名的 三法则 (rule of three)
总结:
在设计一个类的时候,如果我们一个构造函数都没有写,那么 C++ 会帮我们写一个构造函数。只要我们写了一个构造函数,那么 C++ 就不会再帮我们写构造函数了。
构造函数可以重载,可以写很多个,析构函数不能重载,只能写一个。如果我们没有写析构函数,C++会自动帮我们写一个析构函数。那么在工作的时候,我们写的析构函数会被调用,调用完成之后,C++会执行它自动生成的析构函数。
如果我们写的类是一个没有那么复杂的类,我们可以不需要写析构函数。如果一个类只要有这些情况:打开文件、动态分配内存、连接数据库。简单的说:就是只要构造函数里面有了 new 这个关键词,我们就需要自己手动编写析构函数。
那么如果我们写了析构函数,就必须要注意三法则:同时编写:析构函数、赋值构造函数、赋值运算符。
完整的代码:
#include
#include
using namespace std; class NoName{ public: NoName():pstring(new std::string) , i(0), d(0){ cout << "构造函数被调用了!" << endl; } NoName(const NoName & other); ~NoName(); NoName& operator =(const NoName &rhs); private: std::string * pstring; int i; double d; }; NoName::~NoName(){ cout << "析构函数被调用了!" << endl; } NoName::NoName(const NoName & other){ pstring = new std::string; *pstring = *(other.pstring); i = other.i; d = other.d; } NoName& NoName::operator=(const NoName &rhs){ pstring = new std::string; *pstring = *(rhs.pstring); i = rhs.i; d = rhs.d; return *this; } int main(){ NoName a; NoName *p = new NoName; delete p; return 0; }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/222560.html原文链接:https://javaforall.net
