一 数组和new
数组类型变量三个重要限制:
1 数组长度不变
2 在编译时必须知道其长度
3 数组只在定义它的块语句内存在
突破数组的限制
针对2 需要在运行时动态的分配数组
针对3 动态分配的数组一直存在,直到程序显示释放它
自由存储区:又叫做堆。每一个程序在执行时都占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为程序的自由存储区或堆。
C语言使用一对标准库函数:malloc和free
C++则使用new和delete
1 动态数组的定义
int *p = new int [10]; //array of 10 uninitialized ints
返回指向数组第一语速的指针,此返回值初始化了指针 p
在自由存储区中创建数组对象是没有名字的,程序员只能通过其地址间接的访问堆中对象
2初始化动态分配的数组
string *psa = new string [10];
注意:这里分配了对象的内存空间后,将调用string类型的默认构造函数一次初始化数组中的每个函数
int *pia2 = new int [10](); //array of 10 initialized ints
可以在数组长度分配一对空括号,对数组元素做值初始化圆括号要求编译器对数组做值初始化。
i nt *pia2 = new int [10](); 等同于nt *pia2 = new int [10](0);
动态分配的数组全部被初始化为0
3 const 对象的动态数组
const int *pci_ok = new const int [100]();
const string *pci = new const string[100];
当然,创建常量元素不予续修改
4允许动态分配空数组
原因:编译时不知道数组的长度,编写一下代码:
size_t n = get _size();
int *p = new int [n];
如果get_size 返回 0 ,怎么办?
答案是:代码仍然正确执行
C++虽然不允许定义长度为0的数组,但是明确指明调用new动态创建长度为0 的数组时合法的。
char arr[0];//error
int *p = new char [0];
5 动态空间的释放
delete[]表示释放指针所指向的数组空间
delete [] pia;
方括号:如果漏了空方括号对,编译器无法发现错误
可导致少释放了内存空间,产生内存泄漏,严重的运行错误等
二 对象和new
定义变量时,必须指定其数据类型和名字。而动态创建时,只需指定其数据类型,而不必为该对象命名。
int i ;
int *p = new int;
1 动态创建对象的初始化
int i(1024);
int *pi = new int(1024);
string s(10,’9’);
string *ps = new string(10, ‘9’);
2 动态创建对象的默认初始化
对于类类型的对象,用该类的默认构造函数初始化
string *ps = new string ;
内置类型的对象则无初始化
int *pi = new int ;
通常,除了对其复制之外,对未初始化的对象所关联的值的任何使用都没有定义的。
对动态创建的对象做值的初始化
string *ps = new string(); //initialized to empty string
int *pi = new int (); //pi points to an int value-initialized to 0;
cls *pc = new cls(); //pc points to a value-initialized of type cls
对于提供了默认构造函数的类类型string,没有必要对其对性进行值的初始化:无论程序是明确的不初始化哈市要求进行值初始化,都会自动调用其默认构造函数初始化该对象。
3耗尽内存
New失败,系统将抛出名为bad_alloc的一场
4 撤销动态创建的对象
delete pi;
5 0指针的删除
int *ip = 0;
delete ip;
删除0指针式安全
6 在delete之后重设指针的值
执行语句
delete p;后,p变成没有定义。
在很多机器上,尽管p没有定义,蛋仍然存放了它之前所指向对象的地址,然而p所指向的内存已经已经被释放,因此p不再有效。
删除指针后,该指针变成悬垂指针。
悬垂指针 :指向曾经存放对象的内存,蛋该对象已经不再存在了。
悬垂指针往往导致程序的错误,而且很难检测出来
注意: 一旦删除了指针所指向的对象,立即将指针置0,这样就非常清楚的表明指针不再指向任何对象。
7 const 对象的动态分配和回收
const int *pci = new const int(1024);
与其他常量一样,动态创建的const对象必须在创建时初始化,并且一经初始化,其值就不能再修改。与其他const对象的地址一样,由于new返回的地址上存放的是const对象,因此该地址只能付给指向const的指针。
const string *pcs = new const string ;
8 删除const对象
尽管程序员不能够改变const对象的值,但可撤销对象本身。Const对象也是使用删除指针来释放的
delete pci;
程序错误与动态分配内存分配:
1 删除指向动态分配内存的指针失败,因而无法将该块内存返还给自由存储区,删除动态分配内存失败称为“内存泄漏(memory leak)”。内存泄漏很难发现,等程序运行了一段时间后,耗尽内存空间时,内存泄漏才会显露出来。
2 读写已删除的对象。
如果删除指针所指向的对象之后,将指针置为0值,则比较容易检测出这类错误。
3 对同一个 呢此存空间使用两次delete表达式。
当两个指针指向同一个动态创建的对象,删除时就会发生错误。如果在其中一个指针上做delete运算,将该对象的内存空间返还给自由存储区,然后接着delete第二个指针,此时则自由存储区可能会被破坏。
由C++Primer总结。