您的位置:首页 > 编程语言 > C语言/C++

c++ new delete知识总结

2017-07-12 16:16 246 查看
一、C++的动态对象创建

当创建一个C++对象时,会发生两件事:

(1)为对象分配内存

(2)调用构造函数来初始化那个内存

然而,为对象分配内存可以用以下几种方式或在可选择的时间发生:

(1)在静态存储区域,存储空间在程序开始之前就可以分配。这个存储空间在整个运行期间都存在。

(2)无论何时到达一个特殊的执行点(左大括号)时,存储单元都可以在栈上被创建。出了执行点(右大括号),这个存储单元自动被释放。这些栈分配运算内置于处理器的指令集中,非常有效。但是,在写程序的时候,必须知道需要多少个存储单元,以便编译器知道生成正确的指令。

(3)存储单元也可以从一块称为堆的地方分配。这被称为动态内存分配。在运行时调用程序分配这些内存。这就意味着在任何时候可以分配内存以及分配多少内存,当然也需要负责决定何时释放内存。

二、C++的new 和 delete

C++中的解决方法是把创建一个对象所需的所有动作都结合在一个称为new的运算符里。我们当用new创建一个对象时,它就在堆里为对象分配内存并为这块内存调用构造函数。我们可以为类使用任何可用的构造函数,如果构造函数没有参数,可以写没有构造函数参数表的new表达式。

new表达式的反面是delete表达式。delete表达式首先调用析构函数,然后释放内存。如果正在删除的对象的指针是0,将不发生任何事情。为此,我们经常建议在删除指针后立即把指针赋值为0以免对它删除两次,从而产生某些问题。

#include <iostream>

using namespace std;

class B{
public:
B(){
cout<<"class b is created"<<endl;
}
~B(){
cout<<"class b is deleted"<<endl;
}

};

int main(){

B *a=new B;

delete a;
cout<<"-----------------"<<endl;

B *b=new B[3];

//空的方括号告诉编译器产生代码,该代码的任务是将从数组创建时存放在某处的对象数量取回,并为数组的所有对象调用析构函数。
delete []b;
}

最终打印结果为:
class b is created
class b is deleted
-----------------
class b is created
class b is created
class b is created
class b is deleted
class b is deleted
class b is deleted


三、重载局部new delete

重载的new必须有一个size_t参数(不管是局部new还是全局new,不管是new 还是new[])。这个参数由编译器产生并传递给我们,它是要分配内存的对象的长度。必须返回一个指向等于这个长度(或者大于这个长度)的对象的指针。我们首先需要明白的一点就是:operator new()的返回值是一个void*。它所做的是分配内存,而不是完成一个对象建立–直到构造函数调用了才完成对象的创建,它是编译器确保做的动作,不在我们的控制范围之内了,所以我们就没有必要考虑。

当在一个类内部重载new和delete的时候,我们称之为重载局部new delete。为一个类重载new和delete的时候,尽管不必显式的使用static,但是实际上仍是在创建static成员函数。它的语法也和重载任何其它运算符一样。当编译器看到使用new创建自己定义的类的对象时,它会选择相应版本的局部new delete函数去执行。

#include <iostream>

using namespace std;

class A{
public:
static int count;

A(){
cout<<"class a is created"<<endl;
}
~A(){
cout<<"class a is deleted"<<endl;
}

//局部new重载
/*注意:当执行A *a=new A时,会先调用这个局部new重载函数,然后调用了2次构造函数,但返回的对象的内存地址却是相同的一个,因此可以理解为只创建了一个对象,不知道为啥会调用2次构造函数。*/
static void * operator new(size_t size){
cout<<"jubu new is called"<<endl;
count++;
A *a=::new A;

return a;
}

//局部delete重载
static void operator delete(void *p){
cout<<"jubu delete is called "<<p<<endl;
count--;
::delete p;

}

//局部new[]重载
static void * operator new[](size_t size){
cout<<"jubu [] new is called"<<endl;

return operator new(size);
}

//局部delete[]重载
static void operator delete[](void *p){
cout<<"jubu [] delete is called"<<endl;
operator delete(p);
}
};

int A::count=0;

int main(){
A *a=new A;//调用局部重载new
delete a;//调用局部重载delete
cout<<"-----------------"<<endl;

A *b=new A[3];//调用局部重载new[]
delete []b;//调用局部重载delete[]
}
上述程序输出结果为:
jubu new is called
class a is created
class a is created
class a is deleted
jubu delete is called 0x7111a0
-----------------
jubu [] new is called
jubu new is called
class a is created
class a is created
class a is created
class a is created
class a is deleted
class a is deleted
class a is deleted
jubu [] delete is called
jubu delete is called 0x7111a0


四、全局new delete重载

全局new delete重载,即相关的重载方法,写在和main方法同级的代码块中,针对整个系统有效,而上述局部new delete重载只是针对本类有效。

#include <iostream>

using namespace std;

class A{
public:
static int count;

A(){
cout<<"class a is created"<<endl;
}
~A(){
cout<<"class a is deleted"<<endl;
}

//局部new重载
static void * operator new(size_t size){
cout<<"jubu new is called"<<endl;
count++;
A *a=::new A;

return a;
}

//局部delete重载
static void operator delete(void *p){
cout<<"jubu delete is called "<<p<<endl;
count--;
::delete p;

}

//局部new重载
static void * operator new[](size_t size){
cout<<"jubu [] new is called"<<endl;

return operator new(size);
}

//局部delete重载
static void operator delete[](void *p){
cout<<"jubu [] delete is called"<<endl;
operator delete(p);
}
};

int A::count=0;

//全局new重载
void * operator new(size_t size){
if(size==0){
return 0;
}
void *p=malloc(size);
cout<<"quanju new is called "<<p<<endl;
return p;
}
//全局new[]重载
void * operator new[](size_t size){
cout<<"quanju[] new is called "<<endl;
return operator new(size);
}
//全局delete重载
void operator delete(void *p){
cout<<"quanju delete is called "<<p<<endl;
free(p);
}
//全局delete[]重载
void operator delete[](void *p){
cout<<"quanju[] delete is called "<<p<<endl;
operator delete(p);
}

int main(){
int *x=new int(12);
delete x;
cout<<"----------"<<endl;

int *p=new int[10];
delete []p;
cout<<"-----------------"<<endl;

A *a=new A;
delete a;
cout<<"-----------------"<<endl;

A *b=new A[3];
delete []b;
}
上述程序执行结果为:
//int *x=new int(12);
//delete x;
quanju new is called 0x1e11a0
quanju delete is called 0x1e11a0
----------
//int *p=new int[10];
//delete []p;
quanju[] new is called
quanju new is called 0x1e11a0
quanju[] delete is called 0x1e11a0
quanju delete is called 0x1e11a0
-----------------
//A *a=new A;
//delete a;
jubu new is called
quanju new is called 0x1e11a0
class a is created
class a is created
class a is deleted
jubu delete is called 0x1e11a0
quanju delete is called 0x1e11a0
-----------------
//A *a=new A[3];
//delete []a;
jubu [] new is called
jubu new is called
quanju new is called 0x1e11a0
class a is created
class a is created
class a is created
class a is created
class a is deleted
class a is deleted
class a is deleted
jubu [] delete is called
jubu delete is called 0x1e11a0
quanju delete is called 0x1e11a0


五、总结

当局部、全局new delete都被重载后,其和构造方法、析构方法的调用是有顺序的,具体如下图所示:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: