new和delete
c++定义了两个运算符来分配和释放动态内存。new来分配内存,delete来释放内存。
1.new分配内存
①动态内存的分配和初始化
动态分配的内存是无名的,返回一个指向这块内存的指针。 动态内存初始化的方式有三种:
- 默认初始化: 内置类型按内置类型初始化规则初始化,在所有块之外初始化为0,在任何块之内则是未定义的;自定义的类型采用其默认构造函数初始化。
- 直接初始化: 动态开辟的对象会初始化,建议采用这种初始化方式
- 列表初始化: 对vector、数组这种适合使用列表初始化
int *p1=new int;
int *p2=new int(10);
vector<int> *p3=new int{1,2,3,4};
②动态分配的const对象
类似其他任何const对象,对内置类型,一个动态分配的const的对象必须进行初始化。对于一个定义了默认构造函数的自定义类型,可以隐式初始化。动态分配的const对象必须初始化,返回一个指向常量的指针。
const int *p=new const int(10);
const string *ps=new const string;
2.delete释放内存
①释放动态内存
堆区分配的内存,如果我们不手动释放,就会一直占着内存,造成内存泄漏,因此,在动态内存使用完毕后,我们需要用delete手动释放堆区的内存。
如:
int *p=new int(10);
delete p;
②指针值和delete
delete只能释放指向动态分配的内存,或者一个空指针。释放不是new分配的内存,或者将相同的指针值释放多次,其行为都是未定义的:
int i,*p1=&i;
int *p2=nullptr;
int *p3=new int(10);
int *p4=p3;
delete p1;
delete p2;
delete p3;
delete p4;
③delete之后重置指针值
new返回的指针p本身就是个对象,delete p之后,p指向的动态内存空间会被释放,但是p仍然存在,变成了一个野指针(无效指针),对象p在离开块之后会被自动销毁。
我们我们delete之后要保留指针,可以在delete之后将其指向nullptr,但可能有多个指针指向相同的内存,这种方法只对这个指针有效,其他指向动态内存的指针还是野指针。
int main(){
int *p1=new int(10);
int *p2=p1;
delete p1;
p1=nullptr;
return 0;
}
3.使用new和delete常见问题
使用new和delete管理动态内存非常容易发生错误,能用智能指针就不要使用new和delete来管理内存。
下面来介绍new和delete管理动态内存常见的三个问题:
- 忘记delete内存。忘记释放动态内存,会导致“内存泄漏”,这种内存永远不可能被归还给堆区了。如果堆区空间被使用完将不能开辟新的动态内存,造成 “内存耗尽。”
- 使用已经释放掉的对象。 通过在释放内存后,指针变成野指针,使用野指针会造成错误。
- 同一块内存被释放多次。 如果有两个指针指向同一块动态内存,先后释放这两个指针,自由空间可能被破坏。
|