C++中定义了两个运算符来分配和释放内存:new分配内存,delete释放内存。
使用new来动态分配和初化对象
在自由空间分配的内存是无名的,因此new无法为其分配的对象命名,而是返回指向该对象的指针。
new 可以分配基本的数据类型变量,也可以为类分配对象的内存空间,然后返回指向该对象的指针。
如【例1】:
int*ip =newint;//动态分配一个int大小的空间,并返回int类型的指针赋给ip,该变量未被初化
cout <
*ip = 0;//对ip指向的变量进行初始化
cout <
double*dp =newdouble;
cout <
*dp = 1.2;
cout <
string*sp =newstring;//动态分配一个string对象的内存空间,并返回该对象的指针,默认初始化为空
cout <
*sp ="string test.";//对string进行值值
cout <
结果:
-842150451
0
-6.27744e+066
1.2
string test.
New的用法总结:
1.动态分配的对象是默认初始化的
对于基本数据类型的变量的值是不定义的,如上面的ip、dp指向的变量是未定义的,是一个任意值;而对于string,string是一个类,用了string的默认构造函数对基进行初始化。
2.可以用直接初始化方式初始化一个动态分配的对象
【例2】:
int*i_p1 =newint();
int*i_p2 =newint(10);
cout <
cout <
deletei_p1;
deletei_p2;
string*s_p1 =newstring();
string*s_p2 =newstring("hello world");
cout <
cout <
deletes_p1;
deletes_p2;
结果为:
0
10
hello world
用delete释放动态内存
用new分配的内存并不会自己释放,要用delete进行释放后将内存归还给系统。动态内存使用完必后必须用delete释放内存,否则会出现内存泄露。
delete表达式:delete p;//p必对应指针,可以为空指针
Delete完成两个动作:销毁给定指针指向的对象,释放对应内存。
对应【例1】,要对其进行释放内存,如下:
【例3】:
int*ip =newint;//动态分配一个int大小的空间,并返回int类型的指针赋给ip,该变量未被初化
cout <
*ip = 0;//对ip指向的变量进行初始化
cout <
deleteip;//使用完后释放内存
double*dp =newdouble;
cout <
*dp = 1.2;
cout <
deletedp;//使用完后释放内存
string*sp =newstring;//动态分配一个string对象的内存空间,并返回该对象的指针,默认初始化为空
cout <
*sp ="string test.";//对string进行值值
cout <
deletesp;//使用完后释放内存
1.传递给delete的指针必须指向动态分配的内存,或是一个空指针;
【例4】:
inti = 1;
int*p = &i;
deletep;//不能释放非动态分配的内存空间
2.动态分配的内存只能释放一次;
【例5】:
int*ip =newint;
*ip = 0;
cout <
deleteip;//使用完后释放内存
deleteip;//不能重复释放内存
3.动态对象的生存期直到被释放时为止;
如【例6】:
voidfunction()
{
string*s =newstring("new string!");//分配一个动态对象,生存期开始
cout <
}
voiduse_function()
{
function();//调用了function();但未释文s指向的内存,该内存一直存在
}
针对这种情况,使用完动态分配的内存后必须在function()中释放,域返回一个指针,由调用它的函数释放!
方法一:
voidfunction()
{
string*s =newstring("new string!");//分配一个动态对象,生存期开始
cout <
deletes;//用完后释放
}
方法二:
string* function()
{
string*s =newstring("new string!");//分配一个动态对象,生存期开始
cout <
returns;
}
voiduse_function()
{
string*sp = function();
deletesp;//用完后释放
}
4.养成delete之后重置指针为空的习惯
【例7】:
voidfunction()
{
string*s =newstring("new string!");
cout <
deletes;
cout <
}
动态分配数组
相信,数组大家都不陌生,很轻松就可以定义一个指定大小的数组。 很多程序中都会遇到这样一个场景,要使用一个数组,但在程序编写时并不确定其大小,需在程序运行时才知道。这就需要使用动态数组,在运行时动态分配指定大小的数组。
用new分配一个动态数组
语法格式:
T *p = new T[n];
T可以为基本数据类型,也可以为类,new T[n]返回一个指向第一个T类型元素的指针。
【例8】
voidnewIntTest(intn)
{
int*arr =newint[n];//分配一个大小为n的int型数组
for(size_ti = 0; i
{
cout <
}
cout <
string*arrStr =newstring[n];//分配一个大小为n的string型数组
for(size_ti = 0; i
{
cout <
}
cout <
}
可以用数组的类型别名来动态分配数组
typedefintarrInt[5];//arrInt表示42个int的数组类型
int*arr =newarrInt;
初始化动态分配的数组
与分配单个变量和对象一样,动态分配的数组也是默认初始化的。默认的初始化往往不是我们需要的值,我们可以在分配数组时就给定初始化的值。
【例9】:
voidnewIntTest(intn)
{
int*arr =newint[n]();//分配一个大小为n的int型数组
for(size_ti = 0; i
{
cout <
}
cout <
string*arrStr =newstring[n]();//分配一个大小为n的string型数组
for(size_ti = 0; i
{
cout <
}
cout <
}
动态分配一个空数组是合法的,如int*arrInt =newint[0];对于0长度的数组来说,返回的指针类似于一个迭代器中的尾后指针,不可对该指针进行解引用,可以对指针进行加减操作。
释放数组
对于动态分配的数组,同样要在使用完后释放内存。释放数组要用一种特殊形式的delete,格式如下:
delete[]arr;
arr为指向数组首元素的指针。