对象创建
当创建一个c++对象时会发生两件事:
- 为对象分配内存
- 调用构造函数来初始化那块内存
第一步我们能保证实现,需要我们确保第二步一定能发生。c++强迫我们这么做是因为使用未初始化的对象是程序出错的一个重要原因
动态分配内存方法
为了在运行时动态分配内存,c在他的标准库中提供了一些函数,malloc以及它的变种calloc和realloc,释放内存的free,这些函数是有效的、但是原始的,需要程序员理解和小心使用。为了使用c的动态内存分配函数在堆上创建一个类的实例,我们必须这样做
class Person{ public: Person(){ mAge = 20; pName = (char*)malloc(strlen("john")+1); strcpy(pName, "john"); } void Init(){ mAge = 20; pName = (char*)malloc(strlen("john")+1); strcpy(pName, "john"); } void Clean(){ if (pName != NULL){ free(pName); } } public: int mAge; char* pName; }; int main(){ //分配内存 Person* person = (Person*)malloc(sizeof(Person)); if(person == NULL){ return 0; } //调用初始化函数 person->Init(); //清理对象 person->Clean(); //释放person对象 free(person); return EXIT_SUCCESS; }
问题:
1) 程序员必须确定对象的长度。
2) malloc返回一个void*指针,c++不允许将void*赋值给其他任何指针,必须强转。
3) malloc可能申请内存失败,所以必须判断返回值来确保内存分配成功。
4) 用户在使用对象之前必须记住对他初始化,构造函数不能显示调用初始化(构造函数是由编译器调用),用户有可能忘记调用初始化函数。
c的动态内存分配函数太复杂,容易令人混淆,是不可接受的,c++中我们推荐使用运算符new 和 delete.
new
作用:实例化对象
代替:
Person* person = (Person*)malloc(sizeof(Person)); if(person == NULL){ return 0; } person->Init();
使用new关键字,堆区开辟 ,会调用构造
所有new出来的对象,都会返回该类型的指针
malloc 返回void* 还要强转,不会调用构造
delete
释放堆区空间
释放数组加[] 如:delete[] pArr;
注意
1.new出来的对象 不要用void* 去接收,会导致delete无法释放
2.通过new开辟数组,一定会调用构造函数,所以一定要提供默认构造
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; class Person { public: Person() { cout << "默认构造调用" << endl; } ~Person() { cout << "析构调用" << endl; } }; void Test401() { Person* pArr = new Person[10]; //通过new开辟数组,一定会调用构造函数,所以一定要提供默认构造 } int main() { Test401(); system("Pause"); return 0; }
3.栈上开辟数组,可以指定有参构造
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; class Person { public: Person() { cout << "默认构造调用" << endl; } Person(int a) { cout << "默认构造调用" << endl; } ~Person() { cout << "析构调用" << endl; } }; void Test401() { //Person* pArr = new Person[10]; //通过new开辟数组,一定会调用构造函数,所以一定要提供默认构造 Person pArr2[2] = { Person(1), Person(2) }; //栈上开辟数组,可以指定有参构造 }
数组
//创建字符数组 char* pStr = new char[100]; //创建整型数组 int* pArr1 = new int[100]; //创建整型数组并初始化 int* pArr2 = new int[10]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; //释放数组内存 delete[] pStr; delete[] pArr1; delete[] pArr2;
当创建一个对象数组的时候,必须对数组中的每一个对象调用构造函数,除了在栈上可以聚合初始化,必须提供一个默认的构造函数。