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以免对它删除两次,从而产生某些问题。
三、重载局部new delete
重载的new必须有一个size_t参数(不管是局部new还是全局new,不管是new 还是new[])。这个参数由编译器产生并传递给我们,它是要分配内存的对象的长度。必须返回一个指向等于这个长度(或者大于这个长度)的对象的指针。我们首先需要明白的一点就是:operator new()的返回值是一个void*。它所做的是分配内存,而不是完成一个对象建立–直到构造函数调用了才完成对象的创建,它是编译器确保做的动作,不在我们的控制范围之内了,所以我们就没有必要考虑。
当在一个类内部重载new和delete的时候,我们称之为重载局部new delete。为一个类重载new和delete的时候,尽管不必显式的使用static,但是实际上仍是在创建static成员函数。它的语法也和重载任何其它运算符一样。当编译器看到使用new创建自己定义的类的对象时,它会选择相应版本的局部new delete函数去执行。
四、全局new delete重载
全局new delete重载,即相关的重载方法,写在和main方法同级的代码块中,针对整个系统有效,而上述局部new delete重载只是针对本类有效。
五、总结
当局部、全局new delete都被重载后,其和构造方法、析构方法的调用是有顺序的,具体如下图所示:
当创建一个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都被重载后,其和构造方法、析构方法的调用是有顺序的,具体如下图所示:
相关文章推荐
- C++基础知识(七)new和delete
- C++复习要点总结之四New和delete使用
- 深入C++ new/delete,malloc/free 总结
- c/c++笔试题——C++中 new/delete 概念和用法总结
- C++中 new/delete 概念和用法总结
- 【C++总结】C++的new和delete
- C++ — new和delete的总结
- C++基础知识学习:new与delete表达式
- C++中的new与delete总结
- c/c++笔试题——C++中 new/delete 概念和用法总结
- C++中的new和delete——读书笔记总结
- c++中的new/delete
- 关于C++中的new 和 delete
- malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存
- C++内存管理基础之new & delete
- 关于C++当中new和delete操作符重载的一些感想
- C++中有了malloc/free,为什么还需要new/delete?
- C++中的delete—— C++中的new之姊妹篇
- C++的new和delete功能小窥
- C++学习笔记之1:使用相同形式的new和delete