new是在堆上分配内存,它需要用delete释放,否则会造成内存泄漏。
A a 在程序执行完毕后,会自动释放内存。
int main(){
A a;//定义了一个对象
A *p=new A(); //在堆上定义了一个对象,它的指针保存在p里;堆上定义的对象没有名字,必须用指针保存。
return 0;
}// a 到这里的时候,它占用的内存会被释放,而p,除非调用 delete p,否则内存永远不会被回收,指针p丢弃后,
// 那块内存没被释放,无法被再次使用,造成内存浪费
动态分配内存new 关键字
1 动态分配内存,将从堆中分配内存。局部变量一般存储在堆栈中。
2 使用new将从空闲存储区中为对象分配内存,并返回一个指向该对象的指针即该对象的地址。new运算符的特点:
用new运算符分配的对象没有名字,对该对象的操作都要通过指针间接的完成。
3 动态创建数组:int *p=new int[11];
4 耗尽内存:如果程序用完了所有可用的内存,new表达式就有可能失败。如果new表达式无法获得需要的内存空间。系统将会抛出名为bad_alloc 异常。
5 悬垂指针:执行delete p 后只是把p指向的内容销毁了,并没有删除指针p本身,还可以将p重新指向到另一块新的内存块,因此p还指向原来他指向的对象的地址,然而p所指向的内容给销毁释放掉了,因此p不再有效而变得没有意义。
6 常见错误:如果对某个指针动态分配了内存,又把另一个变量的地址付给了这个指针,这时这个指针就指向了一个静态地址,而不是原来的动态的地址。这时候用delete删掉这个指针的时候就会报错,因为delete不能删除静态指针。
#include <iostream>
using namespace std;
class hyong {
public:
int a, b, c;
hyong() {
a = b = c = 0;
}
hyong(int i) {
a = b = c = i;
}
~hyong() {
cout << "xigou" << "/n";
}
};
int main() {
hyong *p = new hyong;
hyong *p1 = new hyong();
cout << p->a << p1->a <<endl; //输出两个0,都调用默认构造函数初始化指针。
int *p2 = new int;
int *p3 = new int();
int *p4 = new int(1); //new分配内存的初始化方式。
//对于类置类型来说p2没有被初始化得到的是一个随机值, p3被初始化为0
//,p4被初始化为1。
cout<<*p2<<endl<<*p3<<endl<<*p4<<endl; //输出一个随机值,一个0,一个1
int i = 10;
delete p4;
cout << *p4 << endl; //p4现在是悬垂指针,delete只是释放掉了指针p4所指向地址的内容,
//但指针p4仍然指向原来的地址, 但没有内容,指针p4仍然可以再指向其他地址。
p4 = &i;
cout << *p4 << endl; //可以对悬垂指针p4重新赋地址。
const int *p5 = new int;
const int *p6 = new int(4);
cout << *p5 << *p6 << endl; //输出一个随机值和4,const常量必须在声明时初始化。
int *p7 = new int[2];
p7[0] = 5;
p7[1] = 6;
cout << p7[0] << p7[1] <<endl; //定义动态数组
//const int *p8=new int[2]; //错误,因为动态数组不能在声明时初始化,而const又必须要求在声明时初始化,发生冲突,出错。
delete p1;
delete p;
//delete p,p1; //注意,如果使用该语句将则只调用一次析构函数。
delete p2, p3, p4, p5, p6;
delete[] p7;
//int *p8=new int(9); int a=8; p8=&a; delete p8; //错误,现在的指针p8重新指向了一个静态的地址,
//用delete删掉一个静态地址将发生错误
}