5.3构造函数和析构函数
构造函数是用于创建对象的特殊成员函数。
当创建对象时,系统自动调用构造函数
构造函数的作用是:
为对象分配空间;对数据成员赋初值;请求其他资源
没有用户定义的构造函数时,系统提供缺省版本的构造函数。
构造函数名与类名相同:类名
构造函数可以重载。
构造函数可以有任意类型的参数,但没有返回类型。
//所有的类默认都有要给构造函数,一个析构函数
//构造函数、析构函数可以重载
//构造函数、析构函数没有返回值
先初始化,后赋值
1 class myclass
2 {
3 public:
4 int num;
5 public:
6 myclass() :num(4)//先初始化
7 {
8 num = 10;//后赋值
9 std::cout << "class create" << std::endl;
10 }
11 };
深拷贝
1 #define _CRT_SECURE_NO_WARNINGS
2 #include <iostream>
3
4 class string
5 {
6 public:
7 char *p;
8 int length;
9 string(int num, char *str)
10 {
11 length = num;//获取长度
12 p = new char[length];//分配内存
13 memset(p, 0, length);//清空
14 strcpy(p, str);//拷贝内容
15 }
16 string(const string & string1)//深拷贝
17 {
18 this->p = new char[string1.length];//分配内存
19 this->length = string1.length;//赋值
20 memset(this->p, 0, this->length);//清空
21 strcpy(this->p, string1.p);//拷贝内容
22 }
23 ~string()
24 {
25 delete[]p;
26 }
27 };
28
29 void main()
30 {
31 string *pstr1 = new string(10, "hello");
32
33 std::cout << pstr1->p << std::endl;
34
35 string *pstr2 = new string(*pstr1);//深拷贝
36
37 std::cout << pstr2->p << std::endl;
38
39 delete pstr1;
40
41 std::cout << pstr2->p << std::endl;
42
43 system("pause");
44 }
//不要重复delete
1 #include <iostream> 2 using namespace std; 3 4 void main() 5 { 6 int num = 10;//栈上 7 8 int *p = new int;//堆上 9 *p = 5; 10 11 std::cout << *p << " " << p << std::endl; 12 13 delete p; 14 delete p;//不要重复delete 15 16 system("pause"); 17 }
p = NULL;//防止重复删除
1 #include <iostream> 2 using namespace std; 3 4 void main() 5 { 6 int *p = new int; 7 8 delete p; 9 10 p = NULL;//防止重复删除 11 12 delete p; 13 14 system("pause"); 15 }
int *p = new int[80];//new只能分配线性
int(*px)[10] = (int(*)[10])p;//二维数组
1 #include <iostream> 2 using namespace std; 3 4 void main() 5 { 6 int *p = new int[80];//new只能分配线性 7 8 int(*px)[10] = (int(*)[10])p;//二维数组 9 10 int data = 0; 11 12 for (int i = 0; i < 8; i++) 13 { 14 for (int j = 0; j < 10; j++) 15 { 16 px[i][j] = data++; 17 std::cout << " " << px[i][j]; 18 } 19 std::cout << endl; 20 } 21 22 system("pause"); 23 }
//空类占1个字节,表示自己存在
//类的对象,数据是独立的,代码是共享的
//没有分配内存,构造函数没有意义
1 #include <iostream> 2 using namespace std; 3 4 //空类占1个字节,表示自己存在 5 //类的对象,数据是独立的,代码是共享的 6 //没有分配内存,构造函数没有意义 7 8 class myclass 9 { 10 public: 11 myclass(); 12 ~myclass(); 13 }; 14 15 void main() 16 { 17 std::cout << sizeof(myclass) << std::endl;//1 18 19 system("pause"); 20 }
全局重载new重载delete
1 #include <iostream> 2 using namespace std; 3 4 void *operator new(size_t size) 5 { 6 std::cout << "全局被调用,内存被分配" << std::endl; 7 if (!size) 8 { 9 return NULL; 10 } 11 else 12 { 13 void *p = malloc(size); 14 return p; 15 } 16 } 17 18 void operator delete(void *p) 19 { 20 std::cout << "全局被调用,内存被释放" << std::endl; 21 free(p); 22 } 23 24 void main() 25 { 26 int *p = new int; 27 28 delete p; 29 30 system("pause"); 31 }
重载new delete数组
1 #include <iostream> 2 using namespace std; 3 4 //全局new delete监视所有分配释放 5 //局部new delete监视某个类的分配释放 6 7 void *operator new(size_t size)//全局重载new 8 { 9 if (!size) 10 { 11 return NULL; 12 } 13 else 14 { 15 std::cout << "全局被调用,内存被分配" << std::endl; 16 void *p = malloc(size); 17 return p; 18 } 19 } 20 21 void operator delete(void *p)//全局重载delete 22 { 23 std::cout << "全局被调用,内存被释放" << std::endl; 24 free(p); 25 } 26 27 void *operator new[](size_t size)//全局重载new数组 28 { 29 return operator new(size);//每个对象挨个调用已经重载好的new,调用构造函数 30 } 31 32 void operator delete[](void *p)//全局重载delete数组 33 { 34 return operator delete(p);//每个对象挨个调用已经重载好的delete,调用析构函数 35 } 36 37 class tansheng 38 { 39 int *p; 40 int length; 41 public: 42 static int count;//计数器 43 44 tansheng() 45 { 46 std::cout << "tansheng被创建" << std::endl; 47 } 48 49 ~tansheng() 50 { 51 std::cout << "tansheng被销毁" << std::endl; 52 } 53 54 static void * operator new(size_t size)//局部重载new 55 { 56 //局部new和全局new分别调用构造函数一次,只有一次有效,因此只有一个指针 57 count++; 58 std::cout << "对象被创建" << std::endl; 59 tansheng *ptem = ::new tansheng;//全局new 60 return ptem; 61 } 62 63 static void * operator new[](size_t size)//局部重载new数组 64 { 65 std::cout << "对象数组被创建" << std::endl; 66 return operator new(size); 67 } 68 69 static void operator delete(void *p)//局部重载delete 70 { 71 count--; 72 std::cout << "对象被销毁" << std::endl; 73 ::delete p;//全局delete 74 } 75 76 static void operator delete[](void *p)//局部重载delete数组 77 { 78 std::cout << "对象数组被销毁" << std::endl; 79 return operator delete(p); 80 } 81 }; 82 83 int tansheng::count = 0;//初始化静态数据成员 84 85 //对象数组被创建 86 //对象被创建 87 //全局被调用,内存被分配 88 //tansheng被创建 89 //tansheng被创建 90 //tansheng被创建 91 //tansheng被创建 92 //tansheng被创建 93 //tansheng被创建 94 //tansheng被销毁 95 //tansheng被销毁 96 //tansheng被销毁 97 //tansheng被销毁 98 //tansheng被销毁 99 //对象数组被销毁 100 //对象被销毁 101 //全局被调用,内存被释放 102 //请按任意键继续. . . 103 104 void main() 105 { 106 tansheng *p = new tansheng[5]; 107 108 delete[]p; 109 110 system("pause"); 111 }
new限定区域分配内存的语法
//p1,p3作为指针变量在栈区,存储的地址指向堆区
//手动释放内存
//p2,p4作为指针变量在栈区,存储的地址在静态区,缓冲区
//自动释放内存,用于分配用完了就不会再用的数据
//避免了内存泄露,牺牲了内存访问的独立性
//可以看到p1,p3的内存地址一直不同,p2,p4的内存地址一直在某个区域
1 #include <iostream> 2 using namespace std; 3 4 const int buf(512);//限定一个常量整数512 5 int N(5);//数组长度 6 char buffer[buf];//在静态区 7 8 //p1,p3作为指针变量在栈区,存储的地址指向堆区 9 //手动释放内存 10 11 //p2,p4作为指针变量在栈区,存储的地址在静态区,缓冲区 12 //自动释放内存,用于分配用完了就不会再用的数据 13 //避免了内存泄露,牺牲了内存访问的独立性 14 15 //可以看到p1,p3的内存地址一直不同,p2,p4的内存地址一直在某个区域 16 17 void main() 18 { 19 double *p1, *p2; 20 21 for (int l = 0; l < 3; l++) 22 { 23 p1 = new double[N];//分配内存,N个元素大小 24 25 p2 = new (buffer)double[N];//指定区域分配内存 26 27 for (int i = 0; i < N; i++) 28 { 29 p1[i] = p2[i] = i + 10.8 + l; 30 std::cout << "p1==" << &p1[i] << " " << p1[i]; 31 std::cout << " p2==" << &p2[i] << " " << p2[i] << std::endl; 32 } 33 34 std::cout << std::endl; 35 } 36 37 double *p3, *p4; 38 39 p3 = new double[N];//分配内存,N个元素大小 40 41 p4 = new (buffer)double[N];//指定区域分配内存 42 43 for (int i = 0; i < N; i++) 44 { 45 p3[i] = p4[i] = i + 10.8; 46 std::cout << "p3==" << &p3[i] << " " << p3[i]; 47 std::cout << " p4==" << &p4[i] << " " << p4[i] << std::endl; 48 } 49 50 system("pause"); 51 }
malloc free和new delete的区别
//malloc和free只会分配内存、释放内存,不会对内存进行操作,不调用构造函数、析构函数
//new和delete自动调用构造函数、析构函数
1 #include <iostream> 2 3 class myclass 4 { 5 public: 6 int x; 7 int y; 8 public: 9 myclass();//构造函数 10 ~myclass();//析构函数 11 }; 12 13 myclass::myclass()//构造函数 14 { 15 std::cout << "被构造" << std::endl; 16 } 17 18 myclass::~myclass()//析构函数 19 { 20 std::cout << "被销毁" << std::endl; 21 } 22 23 void main() 24 { 25 //malloc和free只会分配内存、释放内存,不会对内存进行操作,不调用构造函数、析构函数 26 myclass *p1 = (myclass *)malloc(sizeof(myclass)); 27 free(p1); 28 29 //new和delete自动调用构造函数、析构函数 30 myclass *p2 = new myclass; 31 delete p2; 32 33 system("pause"); 34 }
//初始化列表不可以有this
//error C2059: 语法错误:“this”
1 class mycomplex 2 { 3 public: 4 int x; 5 int y;//xy坐标 6 7 //没有构造,无法使用this初始化 8 mycomplex(int x, int y) :this->x = x, this->y = y//error C2059: 语法错误:“this” 9 { 10 11 } 12 ~mycomplex() 13 { 14 15 } 16 };
//初始化列表不可以有this
解决办法:
1 class mycomplex 2 { 3 public: 4 int x; 5 int y;//xy坐标 6 7 mycomplex(int x, int y) 8 { 9 this->x = x; 10 this->y = y; 11 } 12 ~mycomplex() 13 { 14 15 } 16 };