每一个程序在执行时都占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为程序的自由存储区或者堆。
在自由存储区分配空间:
C:头文件<stdlib.h>中函数 malloc 和free
C++:运算符 new 和delete,不需要库支持
1 定义:
变量:需要指定数据类型,不必命名,new 返回指向新创建对象的指针
int* p=new int;
数组:只需要指定类型和数组长度,不必命名,new 返回指向新分配数组的第一个元素的指针
int * pi=new int[10]; //含有10个int 类型元素的数组
动态分配的数组在编译时知道其长度,在运行时才确定数组长度
size_n n=get_size();
int* p=new int [n];
2 初始化
变量:
int* p=new int(1024); 新创建的对象初始化为9
数组:
int* pi=new int[10]();//圆括号要求编译器做初始化,数组元素被设为0
3异常
当自由存储区(堆)被耗尽 时,程序用完了所有可用的内存,new表达式会失败。如果new 表达式无法获取需要的内存空间,系统将会抛出bad_alloc的异常
try{
int* pi=new int[100]();
}catch(bad_alloc err){
cout<<err.what()<<endl;
}
4撤销动态创建对象
动态分配的内存最后必须进行释放,否则,内存最终将会逐渐耗尽,程序员需要显示地将其占用的存储空间返还给程序的自由存储区(堆)。
变量:delete p;
数组 :delete []pi
[]告诉编译器该指针指向的是自由存储区的数组,而非单个对象。如果遗漏了空方括号,将导致程序运行时出错。
容易出错:
(1)delete指向动态分配内存的指针失败,因而无法将该内存返还给堆。删除动态分配内存失败称为“内存泄露”。当程序运行了一段时间,耗尽了所有内存空间时候,内存泄露才会显露出来。
(2)用已经delete的指针(迷途指针或者悬浮指针)读写已删除的对象。如果删除指针所指的对象之后,将指针置为0值,比较容易检测出来。
当delete一个指针的时候,实际上只是让编译器释放内存,指针本身依然存在,而且指向原先的内存地址(但是编译器可能已经把这块内存分配给其他的数据)这就是迷途指针(悬浮指针)。如果你没有重新赋值就试图再次使用该指针,结果不可预料。
#include<iostream>
#include<string>
using namespace std;
int main()
{
int*p =new int(10);
cout<<*p<<endl;
delete p;
p=0; //给它置0,这样可以预测
*p=20;//看!使用了悬浮指针
cout<<"*p:"<<*p;
}
(3)对同一块内存空间使用两次delete表达式。当两个指针指向同一个动态创建的对象,第一次delete ,将内存返还给堆,第二次delete的时候自由存储区(堆)可能被破坏。