C++基础知识之"new和delete"

fengjingtu

在软件开发过程中,常常需要动态地分配和撤销内存空间,例如对动态链表中结点的插入与删除。

在C语言中是利用库函数malloc和free来分配和撤销内存空间的。

C++提供了较简便而功能较强的运算符new和delete来取代malloc和free函数。

基本语法

注意: new和delete是运算符,不是函数,因此执行效率高。

虽然为了与C语言兼容,C++仍保留malloc和free函数,但建议用户不用malloc和free函数,而用new和delete运算符。

new运算符动态分配堆内存使用形式:

指针变量=new 类型(初始值);//初始化值可缺省

指针变量=new 类型 [表达式];// 创建数组时候,

作用:从堆分配一块“类型”大小的存储空间,返回首地址。

分配失败时候返回NULL;

delete运算符释放已分配的内存使用形式:

delete 指针变量;

delete[] 指针数组变量;

使用例子:

1
2
3
4
5
6
7
8
9
10
11
12
int * pint=new int; 
//开辟一个存放整数的存储空间,返回一个指向该存储空间的地址(即指针)
int *pint=new int(100);
//开辟一个存放整数的空间,初值为100,返回一个指向该存储空间的地址
char *pArrayChar=new char[10];
//开辟一个存放字符数组(包括10个元素)的空间,返回首元素的地址
int * pArrayInt=new int[5][4];
//开辟一个存放二维整型数组(大小为5*4)的空间,返回首元素的地址
float *pfloat=new float(3.14159);
//开辟一个存放单精度数的空间,并指定该实数的初值为//3.14159,将返回的该空间的地址赋给指针变量p
delete pint;
delete [] pArrayChar;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//基本对象的开辟与释放
void new_and_delete()
{
int *a = new int;//开辟一个整数空间,返回指针
int *b = new int(10);//开辟一个整数空间,并初始化为10,返回指针
char *c = new char[10]();
//开辟一个字符数组,长度为10,并初始化为空(整形初始化为0),只能这样初始化;
float *p = new float(3.14);//开辟一个浮点型的空间,初始化为3.14
cout << "*c=" << c << endl;
*a = 10;//
c[0] = 'a';
c[1] = 'b';
c[2] = 'c';
c[3] = '\0';//
cout << "*a=" << *a << endl;
cout << "*b=" << *b << endl;
cout << "*c=" << c << endl;
cout << "*p=" << *p << endl;
delete a;
delete b;
delete[]c;//释放数组空间。
delete p;

}

类对象的动态建立和释放

使用类名定义的对象都是静态的,在程序运行过程中,对象所占的空间是不能随时释放的。但有时人们希望在需要用到对象时才建立对象,在不需要用该对象时就撤销它,释放它所占的内存空间以供别的数据使用。这样可提高内存空间的利用率。

C++中,可以用new运算符动态建立对象,用delete运算符撤销对象

1
2
3
Box *pt; //定义一个指向Box类对象的指针变量pt
pt=new Box; //在pt中存放了新建对象的起始地址
Box *pt=new Box(12,15,18); //执行new时,对新建立的对象进行初始化

在执行delete运算符时,在释放内存空间之前,自动调用析构函数,完成有关善后清理工作。

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
#include<iostream>
using namespace std;

//类对象的开辟与释放

class A
{
public:
A(int a,int b,int c)
{
this->a = a;
this->b = b;
this->c = c;
cout << "A:: construct" << endl;
}
void print()
{
cout << "A->print:a="<<a<<" b="<<b<<" c="<<c << endl;
}
~A()
{
cout << "A::destroy " << a << b << c << endl;
}
int a;
int b;
int c;
};
void new_and_delete2()
{
A *a;
//a = new A;//因为A不存在默认构造方法而出错。
a = new A(1, 2, 3);//new自动调用构造函数
delete a;//delete自动调用析构函数函数

}
void new_and_delete3()//与malloc和free比较
{
A *a;
A *b;
A *c;
A *d;

//以下这四种情况都符合语法,只有在构造函数和析构函数中动态开辟和释放的时候才会出问题
//下面自重情况均没有内存泄漏。

a = new A(1, 2, 3);
a->a = 5;
a->b = 5;
a->c = 5;
a->print();
delete a;//new开辟,delete释放
//正常构造,析构。
cout << "-----------------------------" << endl;

b = new A(1, 2, 3);
b->a = 5;
b->b = 5;
b->c = 5;
b->print();
free(b);//new开辟,free释放
//正常构造,没有析构。
cout << "-----------------------------" << endl;


c = (A *)malloc(sizeof(A));//既然可以开辟,即便A没有默认构造函数
c->a = 5;
c->b = 5;
c->c = 5;
c->print();
free(c);//malloc开辟,free释放
//不构造,不析构。
cout << "-----------------------------" << endl;


d = (A *)malloc(sizeof(A));//既然可以开辟,即便A没有默认构造函数
d->a = 5;
d->b = 5;
d->c = 5;
d->print();
delete d;//malloc开辟,delete释放
//不构造,析构。

cout << "-----------------------------" << endl;
}
int main_new_and_delete()
{
new_and_delete();
new_and_delete2();
new_and_delete3();
cout<<"hello world"<<endl;
system("pause");
return 0;
}