• 【C++】构造函数初始化列表 ⑤ ( 匿名对象 生命周期 | 构造函数 中 不能调用 构造函数 )



    构造函数初始化列表 总结 :

    • 初始化列表 可以 为 类的 成员变量 提供初始值 ;
    • 初始化列表 可以 调用 类的 成员变量 类型的 构造函数 进行成员变量初始化操作 ;
    • 初始化列表 可以 使用 构造函数 中传入的 参数 ;
    • 类初始化时 , 根据定义顺序 , 先调用 成员变量的 构造函数 , 然后调用外部类构造函数 , 析构函数正好相反 ;
    • 实例对象 的 const 成员变量 必须只能在 初始化列表 中进行 初始化 , 所有的构造函数都要进行初始化操作 ;
    • 构造函数 中 不能调用 构造函数 ;




    一、匿名对象 生命周期




    1、匿名对象 生命周期 说明


    调用 类名(构造函数参数) 创建的是 匿名对象 ;

    匿名对象 的 生命周期 仅限于 该 匿名对象 所在的 代码表达式 ,

    一旦 该行代码执行完毕 , 匿名对象就会被销毁 ;


    匿名对象 的 生命周期 仅限于 那一行代码 中 ;


    匿名对象 生命周期 分以下几种情况 :

    • 单独创建 匿名对象 , 不使用变量 接收该 匿名对象 , 匿名对象 的生命周期 仅限于 创建匿名对象 的那一行代码表达式 , 一旦该行代码执行完毕 , 匿名对象 就会被销毁 ;
    • 如果 匿名对象 被用于 对象初始化 , 匿名对象 不会被销毁 , 而是被转为 普通对象 , 赋值给变量 ;
    • 如果 匿名对象 被用于 为现存对象赋值 , 会将 匿名对象 的值赋值给 现有对象 , 赋值完毕后 , 匿名对象仍在本行代码执行结束后销毁 ;

    2、代码示例 - 匿名对象 生命周期


    下面的代码中 , 在 fun 函数中 , 调用 Student(18, 180) 代码 , 创建 Student 类型的匿名对象 , 匿名对象的生命周期 只存在于 这一行代码 , 该行代码执行完毕后 , 匿名对象 就会被 析构 ;

    void fun()
    {
    	cout << "创建匿名对象之前" << endl;
    	// 创建 Student 类型的匿名对象
    	// 匿名对象的生命周期 只存在于 这一句话
    	Student(18, 180);
    	cout << "创建匿名对象之后" << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    代码示例 :

    #include "iostream"
    using namespace std;
    
    class Student
    {
    public:
    	// 带参构造函数
    	Student(int age, int height)
    	{
    		m_age = age;
    		m_height = height;
    		cout << "执行 Student 的构造函数" << endl;
    	}
    
    	~Student()
    	{
    		cout << "执行 Student 的析构函数" << endl;
    	}
    
    public:
    	int m_age;		// 年龄
    	int m_height;	// 身高
    };
    
    void fun()
    {
    	cout << "创建匿名对象之前" << endl;
    	// 创建 Student 类型的匿名对象
    	// 匿名对象的生命周期 只存在于 这一句话
    	Student(18, 180);
    	cout << "创建匿名对象之后" << endl;
    }
    
    
    int main()
    {
    	// 该函数中定义了一个匿名对象
    	fun();
    
    
    	// 控制台暂停 , 按任意键继续向后执行
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    执行结果 :

    创建匿名对象之前
    执行 Student 的构造函数
    执行 Student 的析构函数
    创建匿名对象之后
    Press any key to continue . . .
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述





    二、构造函数 中调用 构造函数




    1、构造函数 中 不能调用 构造函数


    构造函数中 调用 构造函数 是危险行为 ;

    构造函数 中调用 构造函数 , 并不会为本对象进行初始化操作 ;

    构造函数 的调用方式 , 天然就会创建一个 匿名对象 ,

    如果 没有变量 接收 这个 匿名对象 , 该匿名对象 在 本行表达式执行完毕后 , 就会被销毁 ;



    2、代码示例 - 构造函数中调用构造函数


    下面的代码中 ,

    先定义 有参构造函数 ,

    	// 带参构造函数
    	Student(int age, int height)
    	{
    		m_age = age;
    		m_height = height;
    		cout << "执行 Student 的构造函数" << endl;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    然后 , 在无参的 构造函数中 , 调用 有参构造函数 ;

    	// 构造函数中 调用 构造函数 是危险行为
    	Student()
    	{
    		// 构造函数中调用构造函数
    		// 此时 创建 的是匿名对象
    		// 如果 匿名对象 没有被接收 
    		// 就会在 本代码 执行结束后 立刻销毁
    		Student(18, 180);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Student(18, 180) 调用方式 , 会创建一个 匿名对象 ;

    如果 匿名对象 没有被接收 , 就会在 本代码 执行结束后 立刻销毁 ;

    本实例对象 的成员变量实际上没有进行初始化 , 当前为随机值 ;

    这也是 打印 对象成员变量 的值为随机值 的原因 ;

    s.m_age = -858993460 , s.m_height = -858993460
    
    • 1

    代码示例 :

    #include "iostream"
    using namespace std;
    
    class Student
    {
    public:
    	// 带参构造函数
    	Student(int age, int height)
    	{
    		m_age = age;
    		m_height = height;
    		cout << "执行 Student 的构造函数" << endl;
    	}
    
    	// 构造函数中 调用 构造函数 是危险行为
    	Student()
    	{
    		// 构造函数中调用构造函数
    		// 此时 创建 的是匿名对象
    		// 如果 匿名对象 没有被接收 
    		// 就会 本代码 执行结束后 立刻销毁
    		Student(18, 180);
    	}
    
    	~Student()
    	{
    		cout << "执行 Student 的析构函数" << endl;
    	}
    
    public:
    	int m_age;		// 年龄
    	int m_height;	// 身高
    };
    
    void fun()
    {
    	// 创建 Student 类型的匿名对象
    	// 匿名对象的生命周期 只存在于 这一句话
    	Student(18, 180);
    }
    
    
    int main()
    {
    	// 该函数中定义了一个匿名对象
    	//fun();
    
    	Student s;
    	cout << "s.m_age = " << s.m_age << " , s.m_height = " << s.m_height << endl;
    
    
    	// 控制台暂停 , 按任意键继续向后执行
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    执行结果 :

    执行 Student 的构造函数
    执行 Student 的析构函数
    s.m_age = -858993460 , s.m_height = -858993460
    Press any key to continue . . .
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

  • 相关阅读:
    mysql转达梦的python脚本
    CUDA小白 - NPP(9) 图像处理 Statistical Operations
    43.241.18.123哪些问题会导致服务器里面时间错误
    node.js实现结合 RSA 和 AES 加密算法的消息交换加密传输&深入理解 node 中的 crypto 加密模块
    SpringBoot+Vue实现前后端分离的财务管理系统
    SpringCloud: sentinel热点参数限制
    What next? 下一步会怎样?| 经济学人封面社论双语精翻
    聊聊MySQL存储过程
    java毕业设计选题基于SSM项目源码实现的校园食堂点餐|订餐系统
    字符串的左旋和判断一个字符串是否为另外一个字符串旋转之后的字符串。(C语言实现)
  • 原文地址:https://blog.csdn.net/han1202012/article/details/133035110