C++-----对象的生命周期(一)
C++和C的不同点之一在于C++通过类来定义对象,那么对象何时产生,是否需要释放呢???本篇文章将会针对对象的生命周期做出详细介绍。
关于对象的生命周期,我们需要了解类的构造函数,析构函数,拷贝构造函数,赋值运算符重载函数等等。(具体可以参照我的博文)。
首先我们给出以下代码:
#include<iostream> using namespace std; class Test { public: Test(int a = 5,int b = 5):ma(a),mb(b) //拷贝构造函数 {cout<<"Test(int)"<<endl;} ~Test() //析构函数 {cout<<"~Test()"<<endl;} Test(const Test &src):ma(src.ma),mb(src.mb) //拷贝构造函数 {cout<<"Test(const Test&)"<<endl;} Test& operator=(const Test &src) //赋值运算符重载函数 { cout<<"operator="<<endl; ma = src.ma; mb = src.mb; return *this; } private: int ma; int mb; }; Test t1(10,10); int main() { Test t2(20,20); Test t3 = t2; static Test t4 = Test(30,30); t2 = Test(40,40); t2 = (Test)(50,50); /* 构造函数只有一个参数的 Test(val) <====> (Test)val 构造函数有两个参数 Test(a,b) <====> (Test)b 析构顺序:局部对象 静态对象 全局对象 */ t2 = 60; Test *p1 = new Test; Test *p2 = new Test[2]; Test *p3 = &Test(70,70); //指针和对象不是共用一块内存,当语句结束时,析构临时对象 Test &p4 = Test(80,80); //引用和对象是一块内存,语句结束时,不析构 delete p1; delete []p2; return 0; } Test t5(90,90);
执行结果:
Test(int) //普通构造t1 Test(int) //普通构造t5 Test(int) //普通构造t2 Test(const Test&) //t2拷贝构造t3 Test(int) //普通构造t4 Test(int) //普通构造临时对象 operator= //临时对象赋值t2 ~Test() //析构临时对象 Test(int) //普通构造临时对象 operator= //临时对象赋值t2 ~Test() //析构临时对象 Test(int) //普通构造临时对象(隐式生成) operator= //临时对象赋值t2 ~Test() //析构临时对象 Test(int) //普通构造p1指向的无名对象 Test(int) //普通构造p2指向的无名对象 Test(int) //普通构造p2指向的无名对象 Test(int) //普通构造临时对象 ~Test() //析构临时对象 Test(int) //普通构造临时对象 ~Test() //析构p1指向的无名对象 ~Test() //析构p2指向的无名对象 ~Test() //析构p2指向的无名对象 ~Test() //析构p4指向的无名对象 ~Test() //析构t3 ~Test() //析构t2 ~Test() //析构t4 ~Test() //析构t5 ~Test() //析构t1
我们对上面代码及其执行结果进行分析,可的如下结论:
-
对于全局对象,程序一开始,其构造函数就先被执行;程序即将结束前其析构函数将被执行。 对于局部对象,当对象诞生时,其构造函数被执行;当程序流程将离开该对象的声明周期时,其析构函数被执行。 对于静态(static)对象,当对象诞生时其构造函数被执行;当程序将结束时其析构函数才被执行,但比全局对象的析构函数早一步执行。 对于以new方式产生出来的局部对象,当对象诞生时其构造函数被执行,析构函数则在对象被delete时执行。时执行
扩展: