很多时候,我们无法事先知道我们需要多少个元素,因此很难提前进行内存的分配。如果事先分配的空间太小,那么就会装不下。如果事先分配的空间太大,又会造成浪费。因此,需要可以在运行的过程中,动态的对内存进行分配。如果只分配不释放,那么就会白白的浪费我们的内存空间,这也不是我们希望看到的,因此,在我们使用结束以后,还需要可以自行对其进行释放,这样一个动态的分配和释放内存的过程,就是动态内存分配。动态分配的内存对象,我们称之为堆对象。
new分配内存,在c++中使用new运算符,它会动态的创建堆对象,然后,返回新分配对象的指针。值得注意的是,我们必须指定需要分配的类型。
#includeusing namespace std; int main() { // 在分配内存的时候,没有对其进行初始化 int * p1 = new int; // 在分配内存的时候,同时进行初始化 int * p2 = new int(520); cout << *p2 << endl; }
1,使用new分配的对象,都没有名字,只有地址,我们只能通过它给我们的指针操控这个对象。
2,使用new分配对象的过程不一定能够成功,如果内存不足了,会发生没有成功分配新内存的异常。因此在尝试大量分配内存的时候,最好配合异常捕获一起使用。
delete通过new分配的内存,需要通过delete释放。
#includeusing namespace std; int main() { int * p = new int(520); cout << *p << endl; // 通过delete释放new分配的对象 delete p; // 注意:这个对象被释放了,就是已经释放了 // 不应该再尝试使用它了 // cout << *p << endl; }
1,如果你非要使用一个已经delete了的对象会怎么样呢?也许会报错,也许不会报错,甚至还能正常使用。但是实际上,对象delete以后,这个对象就是被释放了,不应该再去使用它。
当然有的刚接触程序的朋友可能不太理解,诶?我这不是还能正常用吗?是不是没有释放啊?实际上,释放一个对象,并不一定非要将其初始化为0,只要将其标注为空闲,下次使用可以直接重新分配和覆盖就可以了。因此,短时间内,你释放掉的这个内存,不一定会马上投入使用,因此在某些实现中可能会造成,delete了的对象还能使用的错觉,实际上并非如此。
2,delete某个指针,只是释放了这个指针指向的对象,并没有初始化这个指针。因此,已经释放的指针可以被重新赋值,但是不应该在没有重新赋值的情况下,再直接拿来使用了。
3,delete只能用于释放new分配的内存,不可以去delete一个没有使用new,直接定义的变量。
4,delete应该只使用一次,不要对同一个地址两次使用delete。因此,在多个指针指向同一个地址的时候,要特别谨慎。因为在这种情况下,很容易造成多次使用delete,或者某个指针已经delete了,其他指针还在使用这个对象。
动态分配对象数组分配一个对象,使用new和delete,但是在分配一个对象数组的时候,需要使用new[]和delete[]。
#includeusing namespace std; int main() { // 使用new[]分配一个对象数组 int * p = new int[10]; // 使用delete[]释放对象数组 delete [] p; }
1,注意new int[10]和new int(10)的不同,new int[10]是分配10个对象的数组,而new int(10)是分配1个int对象,并初始化为10。
2,使用new[]分配的内存必须要使用delete[]释放,不可以直接使用delete。
3,如果通过new或者new[]创建对象,如果未指定初始化,那么会使用默认的初始化,如果是类对象,会调用默认的构造函数。
内存泄漏如果通过new分配的内存,还没有等到使用delete释放,就已经把最后一个保存对象地址的指针给弄丢了,导致这个对象无法到达,造成内存泄漏。或者由于某些原因导致了delete代码没有正常被执行,也会造成内存泄漏。
这种情况可能会发生在:
1,在delete以前,对保存地址的指针进行了重新赋值。
2,保存地址的指针在局部作用域中,当其离开局部作用域时被销毁。
3,在完成delete以前,发生了异常,造成了delete代码未执行。
点击查看全部c++教程



