四十. 构造函数的初始化列表1
#include <iostream>
using namespace std;
class A
{
public:
A(int a)
{
cout<<"A()..."<<endl;
m_a = a;
}
~A()
{
cout<<"~A()..."<<endl;
}
void printA()
{
cout<<"a = "<<m_a<<endl;
}
private:
int m_a;
};
class B
{
public:
B(A& a1, A& a2, int b): m_a1(a1),m_a2(a2)
{
m_b = b;
}
void printB()
{
cout<<"b= "<< m_b <<endl;
m_a1.printA();
m_a2.printA();
}
~B()
{
cout<<"~B()..."<<endl;
}
private:
int m_b;
A m_a1;
A m_a2;
};
int main()
{
A a1(10),a2(100);
B b(a1,a2,1000);
b.printB();
return 0;
}
四十一. 构造函数的初始化列表2(略)
四十二.强化练习1
#include <iostream>
#include <stdio.h>
using namespace std;
class ABCD
{
public:
ABCD(int a, int b, int c)
{
_a = a;
_b = b;
_c = c;
printf("ABCD() construct, a:%d, b:%d, c:%d \n",_a,_b,_c);
}
~ABCD()
{
printf("ABCD() destruct, a:%d, b:%d, c:%d \n",_a,_b,_c);
}
int getA()
{
return _a;
}
private:
int _a;
int _b;
int _c;
};
class MyE
{
public:
MyE(): abcd1(1,2,3), abcd2(4,5,6),m(100)
{
cout<<"MyD().."<<endl;
}
~MyE()
{
cout<<"~MyE()..."<<endl;
}
MyE(const MyE& obj):abcd1(7,8,9), abcd2(10,11,12),m(100)
{
cout<<"MyE(const MyE& obj)"<<endl;
}
public:
ABCD abcd1;
ABCD abcd2;
const int m;
};
int doThing(MyE mye1)
{
cout<<"doThing() mye1.abc1.a:"<<mye1.abcd1.getA()<<endl;
return 0;
}
int run()
{
MyE myE;
doThing(myE);
return 0;
}
int run2()
{
cout<<"run2() starts...."<<endl;
ABCD(400,500,600);
cout<<"run2() ends...."<<endl;
return 0;
}
int main()
{
run2();
return 0;
}
四十三.强化练习2
#include <iostream>
using namespace std;
class MyTest
{
public:
MyTest(int a, int b, int c)
{
_a = a;
_b = b;
_c = c;
}
MyTest(int a, int b)
{
_a = a;
_b = b;
MyTest(a,b,100); //产生新的匿名对象
}
~MyTest()
{
cout<<"~Mytest:"<<_a<<", "<<_b<<", "<<_c<<endl;
}
int getC()
{
return _c;
}
void setC(int val)
{
_c = val;
}
private:
int _a;
int _b;
int _c;
};
int main()
{
MyTest t1(20,30);
return 0;
}
四十四.new和delete1
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
//c语言中
void test1()
{
int *p = (int*)malloc(sizeof(int));
*p = 10;
if(p != NULL)
{
free(p);
p = NULL;
}
int * array_p = (int*) malloc(sizeof(int) *10);
for(int i = 0; i<10; i++)
{
array_p[i] = i +1;
}
for(int i = 0;i<10;i++)
{
printf("%d",array_p[i]);
}
}
//c++中
void test2()
{
int * p = new int;
*p = 10;
if(p != NULL)
{
delete p;
p = NULL;
}
int *array_p = new int[10];
for(int i = 0; i<10; i++)
{
array_p[i] = i +1;
}
for(int i = 0;i<10;i++)
{
cout<< array_p[i]<<" ";
}
cout<<endl;
if(array_p != NULL)
{
delete [] array_p;
}
}
int main()
{
test1();
cout<<endl<<"---------------------------"<<endl;
test2();
return 0;
}
四十五.new和delete2
这里,我们必须对《new与malloc》,《delete与free》这两组关系有比较清晰的认识
delete tp释放的是tp本身,而析构函数,是用来析构new出来的空间。
delete也是类似,delete会做的事,事先去触发析构函数,再去销毁对象。而与此同时,free本身,只是去销毁对象,释放空间。它缺了delete的第一步。
2. 基于上述原因,我们需要掌握delete与delete[]之间的区别
(1)基本数据类型分配和回收空间
针对内置类型(即基本数据类型)使用new分配后的不管是数组还是非数组形式内存空间用两种方式均可,如:
int *a = new int[10];
delete a;//正确
<=>等价于
delete[] a;//正确
代码示例:
#include <iostream>;
using namespace std;
int main()
{
int NUM = 3;
int *a1 = new int[NUM];
cout<<a1<<endl;
delete a1;
cout<<"释放了a1的空间"<<endl;
int *a2 = new int[NUM];
cout<<a2<<endl;
delete[] a2;
cout<<"释放了a2的空间"<<endl;
system("pause");
return 0;
}
=>01294750
释放了a1的空间
01294750
释放了a2的空间
注:此种情况中的释放效果相同,原因在于:分配简单类型内存时,内存大小已经确定,系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数。
它直接通过指针可以获取实际分配的内存空间,哪怕是一个数组内存空间(在分配过程中系统会记录分配内存的大小等信息,此信息保存在结构体_CrtMemBlockHeader中,具体情况可参看VC安装目录下CRT\SRC\DBGDEL.cpp)
它直接通过指针可以获取实际分配的内存空间,哪怕是一个数组内存空间(在分配过程中系统会记录分配内存的大小等信息,此信息保存在结构体_CrtMemBlockHeader中,具体情况可参看VC安装目录下CRT\SRC\DBGDEL.cpp)
(2)自定义类型分配和回收空间(即对象数组的内存管理)
针对自定义类型使用new分配后的空间,若是数组形式的内存空间,两种方式效果截然不同,如:
T *a = new T[10]; delete a;//错误,仅释放了a指针指向的全部内存空间 但是只调用了a[0]对象的析构函数,剩下的从a[1]到a[9]这9个用户自行分配的对应内存空间将不能释放 从而造成内存泄漏。 <!=>效果截然不同 delete[] a;//正确,调用使用类对象的析构函数释放用户自己分配内存空间并且释放了a指针指向的全部内存空间
错误程序示例:
#include <iostream>; using namespace std; class T { public: T() { cout <<"构造T"<<endl; } ~T() { cout <<"析构T"<<endl; } }; int main() { int NUM = 3; T *p1 = new T[NUM]; cout<<p1<<endl; delete p1;//错误释放语句 cout<<"释放了p1空间"<<endl; T *p2 = new T[NUM]; cout<<p2<<endl; delete[] p2;//正确释放语句 cout<<"释放了p2空间"<<endl; system("pause"); return 0; } =>构造T 构造T 构造T 010F4754 析构T 程序崩溃了Debug Assertion Failed! Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
- 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
正确程序示例:
#include <iostream>; using namespace std; class T { public: T() { cout <<"构造T"<<endl; } ~T() { cout <<"析构T"<<endl; } }; int main() { int NUM = 3; T *p1 = new T[NUM]; cout<<p1<<endl; delete[] p1;//正确释放语句 cout<<"释放了p1空间"<<endl; T *p2 = new T[NUM]; cout<<p2<<endl; delete[] p2;//正确释放语句 cout<<"释放了p2空间"<<endl; system("pause"); return 0; } =>构造T 构造T 构造T 1664754 析构T 析构T 析构T 释放了p1空间 构造T 构造T 构造T 1664754 析构T 析构T 析构T 释放了p2空间
- 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
注:在用这些类生成对象数组的时候,用delete[]来释放它们才是王道。
(3)总结,别管那么多,反正如果定义的事单个个体,就delete。
如果定义的是数组,就delete[],这样绝对不会出错