【C++ 类和对象、构造函数与生命周期详解】

发布时间:2026/7/31 4:19:50
【C++ 类和对象、构造函数与生命周期详解】 1.C类和对象类比C语言的结构体和结构体变量。OOP语言的4大特征封装 隐藏 继承 多态C语言的自定义类型struct Data{int data;}C语言的自定义类型struct/class Data{xxx}eg定义一个类---人 命令规则驼峰式命名public、private、protected 访问限定符class Person { public: // 成员方法/成员函数 // Person对象成员变量进行初始化 void init(const char *name, int age, char sex); // 释放资源 防止内存泄漏 void destroy(); // set方法 void setName(const char* name) { if (this-name ! nullptr) { delete[]this-name; } this-name new char[strlen(name) 1]; strcpy(this-name, name); } void setAge(int age) { this-age age; } // get方法 //这里getName和 getSex主要是获取 为防止通过指针直接修改内容要加上const const char* getName() { return this-name; } int getAge() { return this-age; } const char* getSex() { return this-sex M ? 男 : 女; } private: // 成员变量属性 char* name; //对象本身只存储指针4或8字节 //实际字符串数据在堆上可以动态改变大小 int age; char sex; };上述代码里有public和privatepublic部分是公开的private是隐私的。get和set函数是写在类内的。init和destroy函数会定义在类外如下void Person::init(const char* name, int age, char sex) { this-name new char[strlen(name) 1]; strcpy(this-name, name); this-age age; this-sex sex; } void Person::destroy() { delete[]this-name; }注意类外定义成员方法会用到this指针. / -指向当前调用成员方法的对象2.C内存分配 new和deleteC语言堆内存开辟 (char*)malloc(要开辟的内存大小 字节) C库中包含的API堆内存释放 free(内存起始地址)Cnew 类型(初始化的值) #define NULL 0 NULL-0 nullptr 0egint *p new char(10);if (p nullptr) 不能这样判断空指针而是用delete。如上述类外定义的代码因为name是不确定大小的字符串需要动态申请空间建在堆上因此new切记用完要delete。总结5点1.malloc按字节数开辟内存返回值需要强转new按给定的类型进行返回值不需要强转2.malloc只负责开辟内存不初始化new是开辟内存初始化3.malloc开辟内存失败返回空指针new开辟内存失败抛出bad_alloc类型的异常4.malloc不区分单个元素和数组但是new要区分new-malloc初始化5.new属于C编译器提供的运算符sizeofmalloc是c库函数new的使用方法try { int *p new int(10); } catch(const bad_alloc err) { //报错 了解即可 cerr new heap memory fail... endl; } int *p (int*)malloc(sizeof(int) * 10); int *p new int[10][10]分别是指针指向new的一个int类型初始值为10的整型的内存空间指针指向new的一个二维数组10行10列每个元素是int类型初始值0的二维数组的内存空间。new是在堆上申请空间。生命周期结束在delete执行的时候。全局变量/静态布局变量 - data - .data/.bss段局部变量 - 函数的栈上堆内存 - 开发自定义内存生命周期int main() { int* p1 new int(20); // 4字节 int 值为20 delete p1; int* p2 new int[20]; // 80字节 数组 20个元素 每个元素是int delete[]p2; // 3 4 int ** p new int[3][4]; //二维数组 int** p new int* [3]; for (int i 0; i 3; i) { p[i] new int[4]; } for (int i 0; i 3; i) { delete[]p[i]; } delete[]p; } #endif3.构造函数和析构函数构造函数是类的一种特殊的成员函数在创建对象时自动调用用于初始化对象的成员变量。特点自动调用无需手动创建必须和类名完全一致无返回值可以重载多个构造函数负责初始化。没有构造函数需要手动初始化就像上面代码的init有构造函数创建即初始化。析构函数特点没有返回值函数名~类名称参数列表必须是空的对象生命周期结束自动调用析构函数栈上的对象 - 出函数作用域 }全局对象 - 程序结束堆上的对象 - delete的时候。构造函数的定义方式1.默认构造函数无参class Person { public: Person() { this-name nullptr; this-age 0; this-sex M; }}特点不接收任何参数如果没写任何构造函数编译器会自动生成但不初始化成员一旦写了自定义构造函数编译器不再自动生成必须保证成员被初始化否则是野指针/未定义值使用场景Person per1; // ✅ 栈对象 Person* p new Person; // ✅ 堆对象 Person per2[10]; // ✅ 对象数组Person per1; // 创建对象 per1.setName(张三); // ✅ 后续修改直接用 set per1.setAge(20); // ✅ 后续修改直接用 set2.带参构造函数Person(const char* name, int age, char sex) { this-name new char[strlen(name) 1];//字符串长度 1包含\0 strcpy(this-name, name); this-age age; this-sex sex;使用场景Person per1(赵云, 23, M);4.构造函数的生命周期int main() { Person per1(赵云, 23, M); //per1.init(赵云, 23, M); // 初始化函数 - 构造函数 cout per1.getName() endl; cout per1.getAge() endl; cout per1.getSex() endl; //per1.destroy(); // 资源释放 - 析构函数 Person per2(刘备, 40, M); //per2.init(刘备, 40, M); cout per2.getName() endl; per2.setName(孙尚香); per2.setAge(20); cout per2.getName() endl; cout per2.getAge() endl; cout per2.getSex() endl; // per3在堆内存上 // malloc(sizeof(Person)); Person* per3 new Person(张飞, 30, M); // malloc 自动调用构造函数 cout per3-getName() endl; cout per3-getAge() endl; cout per3-getSex() endl; delete per3; // 析构函数 free(per3) // 栈内存上的对象出函数作用域析构先构造的后析构后构造的先析构 //cout per.age endl; Person per5(关羽, 30, M); //per1.init(赵云, 23, M); // 初始化函数 - 构造函数 cout per5.getName() endl; cout per5.getAge() endl; cout per5.getSex() endl; }对比项栈对象堆对象创建Person p赵云23’M‘Person* p new Person“张飞30M;内存位置栈堆生命周期作用域控制程序员控制销毁自动出作用域手动delete析构调用编译器自动调用delete时调用name字符串释放析构函数delete析构函数delete①前两种栈对象带参构造初始化自动释放内存②第三种堆对象new 创建delete 释放③第三个delete 一次释放两块内存对象本身 name 字符串④析构顺序后构造的先析构栈对象先构造的后析构5.其他C提供的命名空间 namespace防止全局空间的名字冲突/污染