• 一文详解构造函数和析构函数


    一、对象的初始化和清理

     C++中面向对象的思想来源于现实,是对现实事物的抽象模拟,具体来说,当我们创建对象的时候,这个对象应该有一个初始状态,当对象销毁之前应该销毁自己创建的一些数据

     对象的初始化和清理也是两个非常重要的安全问题,一个对象或者变量没有初始化,对其使用后果是未知的,同样的使用完一个变量,没有及时清理,也会造成一定的安全问题,C++为了给我们提供这种问题的解决方案,构造函数和析构函数,这两个函数将会被编译器自动调用,完成对象初始化和对象清理工作。

     对象的初始化和清理工作是编译器强制我们要做的事情,即使你不提供初始化操作和清理操作,编译器也会给你增加默认的操作,只是这个默认初始化操作不会做任何事,所以编写类就应该顺便提供初始化函数

    简单的案例

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker {
    
    public:
    	// 构造函数  初始化成员变量 编译器调用
    	Maker()
    	{
    		a = 10;
    		cout << "构造函数" << endl;
    	}
    
        ~Maker()
        {
            // 析构函数
            // 对象销毁前  编译器调用
            cout<<"析构函数"<<endl
    
        }
    
    public:
    	int a;
    };
    
    void test01()
    {
        // 创建对象 分配空间  局部变量在栈区  
        // 调用构造函数
    	Maker m;// 创建对象时 调用构造函数
    	int b = m.a;
    	cout << b << endl;
    }
    
    
    int main()
    {
    	//cout << "hello" << endl;
    
    	test01();
    
    	return EXIT_SUCCESS;
    }
    
    • 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

    有参数构造:

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker {
    
    public:
    	// 构造函数
    	Maker()
    	{
    		a = 10;
    		cout << "构造函数" << endl;
    	}
    
    public:
    	int a;
    };
    
    void test01()
    {
    	Maker m;// 创建对象时 调用构造函数
    	int b = m.a;
    	cout << b << endl;
    }
    
    // 析构函数的作用
    
    class Maker2
    {
    public:
    	// 有参数构造
    	Maker2(const char* name, int age)
    	{
    		cout << "有参数构造" << endl;
    
    		// 从堆区进行申请
    		pName = (char*)malloc(sizeof(char) * (strlen(name) + 1));// 申请字符串长度的字节个数  +1 是因为填充\0
    		strcpy(pName,name);// 赋值字符串   参数直接写成字符串地址即可
    		mAge = age;
    
    	}
    
    	void Print()
    	{
    		cout << "打印参数" << pName << mAge << endl;
    	}
    
    
    private:
    	char* pName;
    	int mAge;
    
    
    };
    
    void test02()
    {
    
    	Maker2 m("hh",11);
    	m.Print();
    
    }
    
    
    int main()
    {
    	test02();
    	return EXIT_SUCCESS;
    }
    
    
    • 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
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    二、析构函数

    析构函数的作用就是在对象销毁之前,回收内存资源

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    // 析构函数的作用
    class Maker2
    {
    public:
    	// 有参数构造
    	Maker2(const char* name, int age)
    	{
    		cout << "有参数构造" << endl;
    
    		// 从堆区进行申请
    		pName = (char*)malloc(sizeof(char) * (strlen(name) + 1));// 申请字符串长度的字节个数  +1 是因为填充\0
    		strcpy(pName,name);// 赋值字符串   参数直接写成字符串地址即可
    		mAge = age;
    	}
    	void Print()
    	{
    		cout << "打印参数" << pName << mAge << endl;
    	}
    
    	~Maker2()
    	{
    		cout << "析构函数 " << endl;
    		//释放堆区空间
    		if (pName != NULL)
    		{
    			free(pName);
    			pName = NULL;
    		}
    	}
    
    private:
    	char* pName;
    	int mAge;
    };
    
    void test02()
    {
    	Maker2 m("hh",11);
    	m.Print();
    }
    int main()
    {
    	test02();
    	return EXIT_SUCCESS;
    }
    
    
    • 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

    三、构造函数可以重载

    
    class Maker3
    {
    public:
    	// 构造函数可以重载
    	Maker3()
    	{
    		// 无参构造函数
    		cout
    	}
    
    	Maker3(int a)
    	{
    		// 有参构造函数
    
    	}
    };
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    构造函数必须声明为public,如果是私有化,创建对象会被报错,没办法调用构造函数

    有对象产生必然会调用构造函数,有对象销毁必然会调用析构函数,有多少次对象产生就会调用多少次构造函数,有多少次对象销毁就会调用多少次析构函数

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    
    class Maker3
    {
    public:
    	// 构造函数可以重载
    	Maker3()
    	{
    		// 无参构造函数
    		cout << "无参数构造" << endl;
    	}
    
    	Maker3(int a)
    	{
    		// 有参构造函数
    		cout << "有参数构造" << endl;
    
    	}
    
    	~Maker3()
    	{
    		// 析构函数
    		cout << "析构函数" << endl;
    	}
    };
    
    void test03()
    {
    	Maker3 m;
    	Maker3 m1(1);
    }
    
    int main()
    {
    	//cout << "hello" << endl;
    
    	test03();
    
    	return EXIT_SUCCESS;
    }
    
    
    • 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

    注意:

    构造函数和析构函数必须是共有权限,否则创建对象时,会报错
    初始化用构造函数,清理使用析构函数,这两个函数是编译器调用
    构造函数可以进行重载
    构造函数没有返回值,不可以使用void,析构函数没有返回值,不能使用void

    四、默认构造函数和默认析构函数

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker
    {
    
    public:
    	// 编译器提供默认的构造函数和析构函数 函数体都是空的
    	Maker()
    	{
    
    	}
    
    	~Maker()
    	{
    
    	}
    
    
    	// 编译器提供默认的构造函数和析构函数
    	void printMaker()
    	{
    		a = 100;
    		cout << a << endl;
    	}
    
    private:
    	int a;
    };
    
    void test()
    {
    	Maker m;
    	m.printMaker();
    }
    
    int main()
    {
    	//cout << "hello" << endl;
    
    	test();
    
    	return EXIT_SUCCESS;
    }
    
    
    • 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

    五、拷贝构造函数

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker
    {
    
    public:
    	// 编译器提供默认的构造函数和析构函数 函数体都是空的
    	Maker()
    	{
    		cout << "构造函数" << endl;
    		a = 20;
    	}
    
        // 拷贝构造函数  参数是对象的引用
    	Maker(const Maker &m)
    	{
    		cout << "拷贝构造函数" << endl;
    		a = m.a;// 赋值成员变量
    	}
    
    	~Maker()
    	{
    
    	}
    
    	// 编译器提供默认的构造函数和析构函数
    	void printMaker()
    	{
    		a = 100;
    		cout << a << endl;
    	}
    
    private:
    	int a;
    };
    
    void test()
    {
    	Maker m;
    	//m.printMaker();
    
    	Maker m1(m);// 用已有的对象生成另一个对象  涉及到构造函数的重载
    	m1.printMaker();
    }
    
    int main()
    {
    	//cout << "hello" << endl;
    
    	test();
    
    	return EXIT_SUCCESS;
    }
    
    
    • 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
    • 56
    • 57

    5.1 编译器提供了默认的构造函数

    C++编译器提供了默认的拷贝构造函数,默认的拷贝构造函数进行了成员变量的简单赋值

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker
    {
    
    public:
    	// 编译器提供默认的构造函数和析构函数 函数体都是空的
    	Maker()
    	{
    		cout << "构造函数" << endl;
    		a = 20;
    	}
    
     //   // 拷贝构造函数  参数是对象的引用
    	//Maker(const Maker &m)
    	//{
    	//	cout << "拷贝构造函数" << endl;
    	//	a = m.a;// 赋值成员变量
    	//}
    
    	~Maker()
    	{
    
    	}
    
    	// 编译器提供默认的构造函数和析构函数
    	void printMaker()
    	{
    		cout << a << endl;
    	}
    
    private:
    	int a;
    };
    
    void test()
    {
    	Maker m;
    	//m.printMaker();
    
    	Maker m1(m);// 用已有的对象生成另一个对象  涉及到构造函数的重载
    	m1.printMaker();
    }
    
    int main()
    {
    	//cout << "hello" << endl;
    
    	test();
    
    	return EXIT_SUCCESS;
    }
    
    • 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

    5.2 拷贝构造函数中形参必须要用引用类型

    如果拷贝构造函数中的形参不是引用类型

    Maker3(const Maker3 m)
    {
    	cout<<"拷贝构造函数"<<endl;
    }
    
    1.Maker3 m2(m1);
    2.const Maker3 m = m1;
    3.const Maker3 m(m1);
    4.const Mkaer3 m = m1;
    5.进入死循环
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    六、构造函数的分类和调用

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker {
    
    public:
    	// 按照参数分类:无参数  有参数
    
    	Maker()
    	{
    		cout << "无参数构造" << endl;
    	}
    
    
    	Maker(int a)
    	{
    		cout << "有参数构造" << endl;
    	}
    
    	// 按照类型:普通构造函数  拷贝构造函数
    	Maker(const Maker& m)
    	{
    		cout << "拷贝构造函数" << endl;
    	}
    };
    
    
    void test()
    {
    	Maker m;// 调用无参数构造函数
    	Maker m1(10);// 调用有参数构造函数
    	Maker m2(m1);// 调用拷贝构造函数
    	Maker m3 = m2;// 调用拷贝构造函数
    	Maker m4 = 10;// 调用有参构造
    }
    
    int main()
    {
    	//cout << "hello" << endl;
    
    	test();
    
    	return EXIT_SUCCESS;
    }
    
    • 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

    七、匿名对象

    匿名对象的声明周期在当前行

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker {
    
    public:
    	// 按照参数分类:无参数  有参数
    
    	Maker()
    	{
    		cout << "无参数构造" << endl;
    	}
    
    
    	Maker(int a)
    	{
    		cout << "有参数构造" << endl;
    	}
    
    	// 按照类型:普通构造函数  拷贝构造函数
    	Maker(const Maker& m)
    	{
    		cout << "拷贝构造函数" << endl;
    	}
    
    	~Maker()
    	{
    		cout << "析构函数" << endl;
    	}
    };
    
    void test01()
    {
    	Maker();// 匿名对象的生命周期在当前行
    	cout << "test01函数结束" << endl;
    }
    
    int main()
    {
    	test01();
    	return EXIT_SUCCESS;
    }
    
    
    • 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

    如果匿名对象前面有名字来接 那么就不是匿名对象 析构函数在函数结束之后 执行

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker {
    
    public:
    	// 按照参数分类:无参数  有参数
    
    	Maker()
    	{
    		cout << "无参数构造" << endl;
    	}
    
    
    	Maker(int a)
    	{
    		cout << "有参数构造" << endl;
    	}
    
    	// 按照类型:普通构造函数  拷贝构造函数
    	Maker(const Maker& m)
    	{
    		cout << "拷贝构造函数" << endl;
    	}
    
    	~Maker()
    	{
    		cout << "析构函数" << endl;
    	}
    };
    
    void test01()
    {
    	Maker();// 匿名对象的生命周期在当前行
    	cout << "test01函数结束" << endl;
    
    
    	Maker m1 = Maker();// 如果匿名对象前面有名字来接  那么就不是匿名对象  析构函数在函数结束之后 执行
    	cout << "函数结束" << endl;
    }
    
    
    
    int main()
    {
    	//cout << "hello" << endl;
    
    	test01();
    
    	return EXIT_SUCCESS;
    }
    
    • 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

    八、拷贝构造函数的调用时机

    8.1 对象以值的方式给函数参数

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker {
    public:
    	// 按照参数分类:无参数  有参数
    	Maker()
    	{
    		cout << "无参数构造" << endl;
    	}
    	Maker(int a)
    	{
    		cout << "有参数构造" << endl;
    	}
    	// 按照类型:普通构造函数  拷贝构造函数
    	Maker(const Maker& m)
    	{
    		cout << "拷贝构造函数" << endl;
    	}
    
    	~Maker()
    	{
    		cout << "析构函数" << endl;
    	}
    };
    
    // 对象以值的方式给函数参数
    void func(Maker m)
    {
    	// 以拷贝构造函数的形式进行赋值
    }
    
    void test01()
    {
    	Maker m1;
    	func(m1); // Maker m = m1
    }
    
    int main()
    {
    	//cout << "hello" << endl;
    	test01();
    	return EXIT_SUCCESS;
    }
    
    • 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

    8.2 vs debug模式下的函数局部对象返回值

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker {
    
    public:
    	// 按照参数分类:无参数  有参数
    
    	Maker()
    	{
    		cout << "无参数构造" << endl;
    	}
    
    
    	Maker(int a)
    	{
    		cout << "有参数构造" << endl;
    	}
    
    	// 按照类型:普通构造函数  拷贝构造函数
    	Maker(const Maker& m)
    	{
    		cout << "拷贝构造函数" << endl;
    	}
    
    	~Maker()
    	{
    		cout << "析构函数" << endl;
    	}
    };
    
    // 对象以值的方式给函数参数
    void func(Maker m)
    {
    	// 以拷贝构造函数的形式进行赋值
    }
    
    // 拷贝构造函数的方式调用
    void test01()
    {
    	Maker m1;
    	func(m1); // Maker m = m1
    }
    
    // 函数的局部对象以值的方式从函数返回
    Maker func2()
    {
    	// 局部对象
    	Maker m;// 无参数构造
    	cout << "局部对象的地址:" << &m << endl;
    
    	return m;
    }
    
    
    // vs 的Debug模式下  会调用拷贝构造  
    void test03()
    {
    	Maker m1 = func2();// 调用拷贝构造函数   vs debug模式下  fun2()中的对象已经释放   m1是新的地址
    	cout << "m1的对象的地址" << &m1 << endl;  // 这里会发现  两个地址不一样  因为函数内部的局部对象 在函数结束之后  会释放内存
    }
    
    
    int main()
    {
    	//cout << "hello" << endl;
    
    	test03();
    
    	return EXIT_SUCCESS;
    }
    
    • 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
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    8.3 vs Release模式下函数局部对象以值的方式从函数返回

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker {
    
    public:
    	// 按照参数分类:无参数  有参数
    
    	Maker()
    	{
    		cout << "无参数构造" << endl;
    	}
    
    
    	Maker(int a)
    	{
    		cout << "有参数构造" << endl;
    	}
    
    	// 按照类型:普通构造函数  拷贝构造函数
    	Maker(const Maker& m)
    	{
    		cout << "拷贝构造函数" << endl;
    	}
    
    	~Maker()
    	{
    		cout << "析构函数" << endl;
    	}
    };
    
    // 对象以值的方式给函数参数
    void func(Maker m)
    {
    	// 以拷贝构造函数的形式进行赋值
    }
    
    // 拷贝构造函数的方式调用
    void test01()
    {
    	Maker m1;
    	func(m1); // Maker m = m1
    }
    
    // 函数的局部对象以值的方式从函数返回
    Maker func2()
    {
    	// 局部对象
    	Maker m;// 无参数构造
    	cout << "局部对象的地址:" << &m << endl;
    
    	return m;
    }
    
    
    // vs 的Relase模式下  不会调用拷贝构造  
    void test03()
    {
    	Maker m1 = func2();// 未调用拷贝构造函数  地址相同   
    	cout << "m1的对象的地址" << &m1 << endl;  // 这里会发现  两个地址一样  release为了节约内存  没有释放函数内部的对象
    }
    
    
    int main()
    {
    	//cout << "hello" << endl;
    
    	test03();
    
    	return EXIT_SUCCESS;
    }
    
    
    • 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
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    九、构造函数的调用规则

    9.1 如果程序员提供有参数构造,那么编译器不会提供默认构造函数,但是会提供默认的拷贝构造函数

    #include
    using namespace std;
    # define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker
    {
    public:
    	Maker(int a)
    	{
    		cout << "有参数构造函数" << endl;
    	}
    
    
    };
    
    // 如果程序员提供了有参数构造函数   那么编译器不会提供默认的构造函数  函数重载
    void test01()
    {
    	//Maker m;// 报错
    	Maker m(10);// 调用有参构造函数
    	Maker m1(m);// 编译器提供默认的拷贝构造函数
    }
    
    int main()
    {
    	test01();
    
    	return EXIT_SUCCESS;
    }
    
    
    • 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

    9.2 如果程序员提供了拷贝构造函数 那么编译器不会提供默认的构造函数和默认的拷贝构造函数

    #include
    using namespace std;
    # define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker
    {
    public:
    	Maker(const Maker& m)
    	{
    		cout << "拷贝构造函数" << endl;
    	}
    
    
    };
    
    // 如果程序员提供了有参数构造函数   那么编译器不会提供默认的构造函数  函数重载
    void test01()
    {
    	//Maker m;// 报错
    }
    
    // 如果程序员提供了拷贝构造函数  那么编译器不会提供默认构造函数和默认的拷贝构造函数
    void test02()
    {
    	Maker m;
    }
    
    int main()
    {
    
    
    	return EXIT_SUCCESS;
    }
    
    
    • 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

    十、多个对象的构造函数和析构函数

    10.1 多个对象的构造函数和析构函数的规则

    • 如果类有成员对象 那么先调用成员对象的构造函数 在调用本身的构造函数
    • 析构函数的调用顺序相反
    • 成员对象的构造函数调用和定义顺序一样
    • 如果有成员对象 那么实例化对象时,必须保证成员对象的构造和析构能被调用
    #include
    using namespace std;
    # define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class BMW
    {
    public:
    	BMW()
    	{
    		cout << "BMW() 构造" << endl;
    	}
    
    	~BMW()
    	{
    		cout << "BMW析构函数" << endl;
    	}
    };
    
    
    class Buiker
    {
    public:
    	Buiker()
    	{
    		cout << "Buiker() 构造" << endl;
    	}
    
    	~Buiker()
    	{
    		cout << "Buiker析构函数" << endl;
    	}
    };
    
    class Maker
    {
    public:
    	Maker()
    	{
    		cout << "Maker构造" << endl;
    	}
    
    	~Maker()
    	{
    		cout << "maker析构函数" << endl;
    	}
    
    private:
    	BMW bmw;//成员对象
    	Buiker bui;
    
    
    };
    
    void test01()
    {
    	// 如果类有成员对象  那么先调用成员对象的构造函数  在调用本身的构造函数
    	// 析构函数的调用顺序相反
    	// 成员对象的构造函数调用和定义顺序一样
    	// 如果有成员对象  那么实例化对象时,必须保证成员对象的构造和析构能被调用
    	Maker m;
    }
    
    
    int main()
    {
    
    	test01();
    
    
    	return EXIT_SUCCESS;
    }
    
    • 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
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    10.2 多个对象初始化列表

    #include
    using namespace std;
    # define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class BMW
    {
    public:
    	BMW(int a)
    	{
    		cout << "BMW() 构造" << a<<endl;
    	}
    
    	~BMW()
    	{
    		cout << "BMW析构函数" << endl;
    	}
    };
    
    
    class Buiker
    {
    public:
    	Buiker()
    	{
    		cout << "Buiker() 构造" << endl;
    	}
    
    	~Buiker()
    	{
    		cout << "Buiker析构函数" << endl;
    	}
    };
    
    class Maker
    {
    public:
    	// 初始化列表
    	// 注意:初始化列表只能写在构造函数
    	Maker() :bmw(10)
    	{
    		cout << "Maker构造" << endl;
    	}
    
    	~Maker()
    	{
    		cout << "maker析构函数" << endl;
    	}
    
    private:
    	BMW bmw;//成员对象
    	Buiker bui;
    };
    
    void test01()
    {
    	// 如果类有成员对象  那么先调用成员对象的构造函数  在调用本身的构造函数
    	// 析构函数的调用顺序相反
    	// 成员对象的构造函数调用和定义顺序一样
    	// 如果有成员对象  那么实例化对象时,必须保证成员对象的构造和析构能被调用
    	Maker m;
    }
    
    // 初始化列表是调用成员对象的指定构造函数
    void test02()
    {
    	Maker m;
    }
    
    
    int main()
    {
    
    	test02();
    
    
    	return EXIT_SUCCESS;
    }
    
    
    • 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
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    或者:构造函数需要加上参数

    #include
    using namespace std;
    # define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class BMW
    {
    public:
    	BMW(int a)
    	{
    		cout << "BMW() 构造" << a<<endl;
    	}
    
    	~BMW()
    	{
    		cout << "BMW析构函数" << endl;
    	}
    };
    
    
    class Buiker
    {
    public:
    	Buiker()
    	{
    		cout << "Buiker() 构造" << endl;
    	}
    
    	~Buiker()
    	{
    		cout << "Buiker析构函数" << endl;
    	}
    };
    
    class Maker
    {
    public:
    	// 初始化列表
    	// 注意:初始化列表只能写在构造函数
    
    	// 构造函数可以写参数  初始化直接写入参数
    	Maker(int a) :bmw(a)
    	{
    		cout << "Maker构造" << endl;
    	}
    
    	~Maker()
    	{
    		cout << "maker析构函数" << endl;
    	}
    
    private:
    	BMW bmw;//成员对象
    	Buiker bui;
    
    
    };
    
    // 初始化列表是调用成员对象的指定构造函数
    void test02()
    {
    	Maker m(1);
    }
    
    
    int main()
    {
    
    	test02();
    
    
    	return EXIT_SUCCESS;
    }
    
    
    • 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
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    注意:如果使用了初始化列表,那么所有的构造函数都要写初始化列表

    #include
    using namespace std;
    # define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class BMW
    {
    public:
    	BMW(int a)
    	{
    		cout << "BMW() 构造" << a<<endl;
    	}
    
    	~BMW()
    	{
    		cout << "BMW析构函数" << endl;
    	}
    };
    
    
    class Buiker
    {
    public:
    	Buiker()
    	{
    		cout << "Buiker() 构造" << endl;
    	}
    
    	~Buiker()
    	{
    		cout << "Buiker析构函数" << endl;
    	}
    };
    
    class Maker
    {
    public:
    	// 初始化列表
    	// 注意:初始化列表只能写在构造函数
    
    	// 构造函数可以写参数  初始化直接写入参数
    	Maker(int a) :bmw(a)
    	{
    		cout << "Maker构造" << endl;
    	}
    	
    	// 拷贝构造函数也要协商初始化列表
    	Maker(const Maker& m) :bmw(4)
    	{
    		// 注意 如果使用了初始化列表 那么所有的构造函数都要写
    	}
    
    	~Maker()
    	{
    		cout << "maker析构函数" << endl;
    	}
    
    private:
    	BMW bmw;//成员对象
    	Buiker bui;
    
    
    };
    
    
    
    // 初始化列表是调用成员对象的指定构造函数
    void test02()
    {
    	Maker m(1);
    }
    
    
    int main()
    {
    	test02();
    	return EXIT_SUCCESS;
    }
    
    • 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
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    
    #include
    using namespace std;
    # define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class BMW
    {
    public:
    	BMW(int a)
    	{
    		cout << "BMW() 构造" << a<<endl;
    	}
    
    	~BMW()
    	{
    		cout << "BMW析构函数" << endl;
    	}
    };
    
    
    class Buiker
    {
    public:
    	Buiker(int b)
    	{
    		cout << "Buiker() 构造" << endl;
    	}
    
    	~Buiker()
    	{
    		cout << "Buiker析构函数" << endl;
    	}
    };
    
    class Maker
    {
    public:
    	// 初始化列表
    	// 注意:初始化列表只能写在构造函数
    	// 构造函数可以写参数  初始化直接写入参数
    	Maker(int a) :bmw(a),bui(1)
    	{
    		cout << "Maker构造" << endl;
    	}
    
    	Maker(const Maker& m) :bmw(4),bui(1)
    	{
    		// 注意 如果使用了初始化列表 那么所有的构造函数都要写
    	}
    
    	~Maker()
    	{
    		cout << "maker析构函数" << endl;
    	}
    
    private:
    	BMW bmw;//成员对象
    	Buiker bui;
    
    
    };
    
    
    // 初始化列表是调用成员对象的指定构造函数
    void test02()
    {
    	Maker m(1);
    }
    
    
    int main()
    {
    	test02();
    	return EXIT_SUCCESS;
    }
    
    • 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
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    构造函数的参数填写所有参数,初始化列表写成参数

    #include
    using namespace std;
    # define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class BMW
    {
    public:
    	BMW(int a)
    	{
    		cout << "BMW() 构造" << a<<endl;
    	}
    
    	~BMW()
    	{
    		cout << "BMW析构函数" << endl;
    	}
    };
    
    
    class Buiker
    {
    public:
    	Buiker(int b)
    	{
    		cout << "Buiker() 构造" <<b<< endl;
    	}
    
    	~Buiker()
    	{
    		cout << "Buiker析构函数" << endl;
    	}
    };
    
    class Maker
    {
    public:
    	// 初始化列表
    	// 注意:初始化列表只能写在构造函数
    	// 构造函数可以写参数  初始化直接写入参数
    	Maker(int a,int b) :bmw(a),bui(b)
    	{
    		cout << "Maker构造" << endl;
    	}
    
    	Maker(const Maker& m) :bmw(4),bui(1)
    	{
    		// 注意 如果使用了初始化列表 那么所有的构造函数都要写
    	}
    
    	~Maker()
    	{
    		cout << "maker析构函数" << endl;
    	}
    
    private:
    	BMW bmw;//成员对象
    	Buiker bui;
    
    };
    
    // 初始化列表是调用成员对象的指定构造函数
    void test02()
    {
    	Maker m(1,2);
    }
    
    int main()
    {
    	test02();
    	return EXIT_SUCCESS;
    }
    
    
    • 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
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    总结:

    • 初始化列表是干什么用的,指定调用成员对象的某个构造函数
    • 初始化列表只能写在构造函数旁边
    • 如果使用了初始化列表 那么所有的构造函数都要写初始化列表
    • 如果有多个对象需要指定调用某个构造函数,需要使用逗号隔开
    • 可以使用对象的构造函数参数传递数值给成员对象的变量

    十一、对象的深浅拷贝

    11.1 默认的拷贝构造函数进行了简单的赋值操作

    拷贝构造函数只是复制值 没有复制内存空间

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker {
    
    public:
    
    	Maker(int a, int b)
    	{
    		id = a;
    		age = b;
    	}
    
    	void print()
    	{
    		cout << "id = " << id << " age = " << age << endl;
    	}
    
    
    private:
    	int id;
    	int age;
    
    
    };
    
    void test01()
    {
    	Maker a(1, 1);
    	a.print();
    
    	Maker b(a);// 拷贝构造函数  浅复制
    	b.print();
    }
    
    int main()
    {
    	test01();
    
    	return EXIT_SUCCESS;
    }
    
    
    • 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

    浅拷贝的问题:同一块内存空间被释放两次

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker {
    
    public:
    
    	Maker(int a, int b)
    	{
    		id = a;
    		age = b;
    	}
    
    	void print()
    	{
    		cout << "id = " << id << " age = " << age << endl;
    	}
    
    
    private:
    	int id;
    	int age;
    
    
    };
    
    class Student {
    public:
    	Student(const char* name, int Age)
    	{
    		pName = (char*)malloc(strlen(name) + 1);// 申请堆区空间
    		strcpy(pName,name);// 复制内容
    		age = Age;
    	}
    
    	// 申请堆区空间 一定要释放
    	~Student()
    	{
    		if (pName != NULL)
    		{
    			free(pName);
    			pName = NULL;
    		}
    	}
    
    	void print()
    	{
    		cout << "名字 = " << pName << "年纪 = " << age << endl;
    	}
    
    private:
    	char* pName;
    	int age;
    };
    
    void test01()
    {
    	Maker a(1, 1);
    	a.print();
    
    	Maker b(a);// 拷贝构造函数  浅复制
    	b.print();
    }
    
    
    void test02()
    {
    	Student a("xxx",1);
    	a.print();
    
    	// 复制的是地址
    
    	// 导致同一块内存地址空间被析构函数销毁两次
    	Student b(a);
    	b.print();
    }
    
    int main()
    {
    	test02();
    
    	return EXIT_SUCCESS;
    }
    
    • 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
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    11.2 深拷贝

    重写拷贝构造函数即可,本质上还是重新申请一块堆区空间

    #include
    using namespace std;
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    class Maker {
    
    public:
    
    	Maker(int a, int b)
    	{
    		id = a;
    		age = b;
    	}
    
    	void print()
    	{
    		cout << "id = " << id << " age = " << age << endl;
    	}
    
    
    private:
    	int id;
    	int age;
    
    
    };
    
    class Student {
    public:
    	Student(const char* name, int Age)
    	{
    		pName = (char*)malloc(strlen(name) + 1);// 申请堆区空间
    		strcpy(pName,name);// 复制内容
    		age = Age;
    	}
    
    	// 重载拷贝构造函数
    	Student(const Student& stu)
    	{
    		cout << "自己的拷贝构造函数" << endl;
    		// 重新申请一块内存空间
    		pName = (char*)malloc(sizeof(char) * (strlen(pName) + 1));
    		// 拷贝数据
    		strcpy(pName,stu.pName);
    		age = stu.age;
    	}
    
    
    	// 申请堆区空间 一定要释放
    	~Student()
    	{
    		if (pName != NULL)
    		{
    			free(pName);
    			pName = NULL;
    		}
    	}
    
    	void print()
    	{
    		cout << "名字 = " << pName << "年纪 = " << age << endl;
    	}
    
    private:
    	char* pName;
    	int age;
    };
    
    void test01()
    {
    	Maker a(1, 1);
    	a.print();
    
    	Maker b(a);// 拷贝构造函数  浅复制
    	b.print();
    }
    
    
    void test02()
    {
    	Student a("xxx",1);
    	a.print();
    
    	// 复制的是地址
    
    	// 导致同一块内存地址空间被析构函数销毁两次
    	Student b(a);
    	b.print();
    }
    
    int main()
    {
    	test02();
    
    	return EXIT_SUCCESS;
    }
    
    
    
    • 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
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
  • 相关阅读:
    python最优化算法实战---线性规划之内点法
    ContextInfo.get_full_tick 获取最新分笔数据
    MySQL 连接出现 Authentication plugin ‘caching_sha2_password的处理方法(使用第二种)
    友元和优化
    springcloudalibaba架构(31):SpringCloud实现用户信息在微服务之间传递
    ChinaSkills技能大赛网络系统管理Debian模块||StorageSrv的ShellScript配置详解
    28. Python 列表的切片取值
    QCC51XX---Earbud启动流程分析
    移动安全规范 — 2 -蓝牙安全规范
    华为交换机vlan划分、telnet 管理地址配置
  • 原文地址:https://blog.csdn.net/qq_44653420/article/details/126911837