new / delete
new int;
new Stash; //new一个类, 分配空间之后,调用构造函数.
new int[10];
delete p; //先调用析构函数,再释放空间
delete[] p; //
new带着[],则delete也带着[].
eg:
int* psome = new int[10];
new 10个int空间,交给psome指针.
delete [] psome;
带[]释放,因为[]告诉some指的是很多东西. 带[] 将调用很多个析构.
若不带[]释放,空间会被回收,但是告诉psome所指的对象只有一个,只会调用一个析构.
new过程
eg:
int *p = new int;
int *a = new int[10];
Student *q = new Student;
Student *r = new Student[10];
(1). 在C++的运行库实现了new过程(前提是空间不是很大),否则则需要
找操作系统要内存.
(2). int *p = new int; 在堆里寻找一块合适的空间,在这个空间放int, 指针p指向这个int. 同时有一张表产生,表会记录申请的内存地址和内存大小(字节为单位).
int *a = new int[10]; ……
Student *q = new Student;……
Student *r = new Student[10];……
delete过程
delete p;
p的地址在表中查找,在不在里面. 如果在,则把相应内存大小收回.
同时把表也删除了.
a++;
delete [] a; //在表中找不到a的地址, 程序运行出错.
delete q; //先析构,在空间回收
首先调用析构, 如何知道调用Student的析构呢?
原始:q的类型知道, 编译知道,编译时会插入调用析构的语言.
delete r; //调用一个析构,然后资源回收
delete[] r; //调用多个析构,然后资源回收
#include "stdafx.h"
#include <iostream>
using namespace std;
class A
{
private:
int i;
public:
A()
{
i = 0;
cout << "A::A()" << endl;
}
~A()
{
cout << "A::~A(), i = " << i << endl;
}
public:
void set(int i)
{
this->i = i;
}
void f() { cout << "hello"; }
};
int main()
{
A* p = new A[10]; //先申请内存,然后调用构造函数
//A::A()10次
for (int i = 0; i < 10; i++)
{
p[i].set(i);
}
delete p; //先调用构造函数,由于没有[],则只调用一次
//A::~A(), i = 0
//Visual Studio报错:触发一个断点
return 0;
}
#include "stdafx.h"
#include <iostream>
using namespace std;
class A
{
private:
int i;
public:
A()
{
i = 0;
cout << "A::A()" << endl;
}
~A()
{
cout << "A::~A(), i = " << i << endl;
}
public:
void set(int i)
{
this->i = i;
}
void f() { cout << "hello"; }
};
int main()
{
A* p = new A[10]; //先申请内存,然后调用构造函数
//A::A()10次
for (int i = 0; i < 10; i++)
{
p[i].set(i);
}
delete[] p; //先调用构造函数,调用10次,并且顺序是颠倒的
//A::~A(), i = 9
//A::~A(), i = 8
//A::~A(), i = 7
//A::~A(), i = 6
//A::~A(), i = 5
//A::~A(), i = 4
//A::~A(), i = 3
//A::~A(), i = 2
//A::~A(), i = 1
//A::~A(), i = 0
return 0;
}
建议
- 不要用delete释放不是new申请的空间
- 不要2次释放同一个空间
- new带[],delete带[]
- new不带[], delete不带[]
- delete null pointer是安全的
int main()
{
int *p = 0;
delete p; //这种写法是安全的
return 0;
}
#include "stdafx.h"
#include <iostream>
using namespace std;
class A
{
private:
int i;
int *p; //定义成员变量指针
public:
A()
{
p = 0; //构造函数指针为空
i = 0;
cout << "A::A()" << endl;
}
~A()
{
if(p)
delete p; //析构函数delete
cout << "A::~A(), i = " << i << endl;
}
public:
void set(int i)
{
this->i = i;
}
void f() { p = new int; } //成员函数内,new
};
//new了之后,程序不delete,程序没问题.
//原因:现在的操作系统都是多进程操作系统,程序每一次运行时新的进程,这个程序起来,操作系统分配空间,4G蓄奴空间。进程结束空间就会回收.
//但是程序一直要跑的,eg:手机的程序。内存泄漏
int main()
{
A a;
return 0;
}
注意事项
若类的成员变量有指针, 成员函数里new, 则需要在构造函数中p =0, 析构函数中if(p) delete p;