6.2 new 和 delete 运算符
来源:互联网 发布:php单选框提交 编辑:程序博客网 时间:2024/04/25 17:56
Q1:new运算符
• new运算符是由两个步骤组成
1. 通过适当的new运算符函数的实例,配置所需要的内存
2. 给配置得来的对象设立初值
Eg:
int * pt = new int(5); //实际操作如下: int * pt; if(pt = _new(sizeof(int))) *pi = 5; //通过构造函数配置类对象的方式相同: Point * pt = new Point; //实际操作如下: Point * pt; if(pt = _new(sizeof(Point))) pt = Point::Point(pt);
• 要求每一次new的调用都必须传回一个独一无二的指针,因此哪怕new申请的空间是0,也会分配一个字节的内存空间,用来返回独一无二的指针
*注:在g++中,new int(0),将返回一个唯一的非空指针,其中存放 “\0”,可用来释放
*注:在VS中,new int(0)将返回一个唯一的非空指针,其内容未定义,可用来释放
• new运算符实例的实现:(通过malloc实现内存分配)
extern void * operator new(size_t size) { if(size ==0) size = 1; //用来确保返回的是独一无二的非空指针 void * last_alloc; while(!(last_alloc = malloc(size))) { if(_new_handler) //允许用户提供属于自己的_new_handler()函数,自行进行内存分配 (*_new_handler)(); else return 0; } return last_alloc; }
Q2:delete运算符
• delete运算符也分为两个步骤:
若是类类型,则需要先调用析构函数销毁对象
释放内存空间
Eg:
int * pt = new int(4); delete pt; //实际执行操作如下: if(pt != 0) _delete(pt); //对类类型指针,先调用析构函数 Point * pt = new Point; delete pt; //实际执行操作如下: if(pt != 0) { Point::~Point(pt); _delete (pt); }
• delete 作用在指针上后,该地址上的对象不再合法,但是该地址仍然是合法的
• delete 运算符也是以标准的C free()实现的:
external void operator delete(void * ptr) { if(ptr) { free((char *)ptr); } }
Q3:new与 malloc的区别:
1. 性质上:new 是运算符,malloc是函数
2. 功能上:new 分配内存空间并初始化该空间,malloc仅分配内存空间
3. 实现上:new 通过malloc分配空间,malloc即为分配空间的函数
Q4:针对数组的 new 语意
• 当用 new 定义内置类型数组或POD类型数组,new 操作只是简单的内存分配与释放操作,将不会调用vec_new()函数(该函数功能是把默认构造函数作用于数组中每个元素之上)
Eg:
int * p = new int[5]; //真实操作如下: int * p = (int*)_new(5 * sizeof(int));
• 如果类定义了默认构造函数,则vec_new()就会被调用,配置并构造类对象组成的数组
Eg:
Point * p = new Point[10]; //真实操作如下: Point *p; p = vec_new(0, sizeof(Point), 10, &Point::Point(), &Point::~Point());
• 在构造类类型数组过程中,如果想要进行异常处理,需要将析构函数传送给vec_new(),因为如果构造过程中出错,需要将已构造的对象析构并释放,然后才抛出异常
• 出于效率考虑,在调用 delete 运算符时,需要指明维数(但不需要指明元素个数),否则,运算符将该指针作为一个对象看待,并释放该数组中的第一个元素,而其他元素仍然存在
• new 操作返回的指针应记录元素个数,记录元素个数有两个方法:
cookie:为vec_new()所传回的每一个内存块配置一个额外的word,把元素个数放在这个word中
维护一个“联合数组”:该数组中放置指针及其大小
• 对派生类而言:
Eg:
Point * ptr = new Point3d[10]; delet ptr;
希望delete 操作调用 Point 和 Point3d 的析构函数各十次。
• 施行于数组上的析构函数,是根据交给vec_delete()函数的“被删除的指针类型”来调用析构函数的。
*因此,对上例中,将只调用 Point::~Point()
• 只能在程序员层面进行手动调用,而不是依赖语言执行
for(size_t i(0);i < elem_cnt;++i) { Point3d * p = (Point3d*)(&(ptr[i])); delete p; }
Q5:Placement Operator new的语意
• placement new是重载operator new的一个标准、全局的版本,它不能被自定义的版本代替(不像普通的operator new和operator delete能够被替换成用户自定义的版本)。
• placement new 需要第二个参数,类型为 void*,其函数原型如下:
void * operator new(size_t,void *p) { return p; }
• 使用实例:
Eg:
Point * pt = new Point; Point * ptn = new(pt)Point;
上述代码将 pt 所指的内存空间放置新产生的 Point 对象,new运算符新增的参数是用来指定内存空间的
• placement new 运算符的功能:既能决定对象放置在哪里,也能保证会执行对象的构造函数
Eg:
Point * ptn = new(pt)Point; //实际操作如下: Point * ptn = (Point*)(pt); if(ptn != 0) ptn = Point::Point(ptn);
• 需要注意:如果 placement operator 在原已存在的一个对象上构造新的对象,哪怕该对象定义了析构函数,也不会调用其析构函数,需要程序员手动调用
• 指定的内存块的指针类型:要么与新分配对象同类型,要么是新鲜的内存
注:新鲜内存的定义方式:char p = new char[sizof(Point)];
• 对派生类需要注意:
Eg:
struct T { int j; virutal void f(); } struct TT : public T { virtual void f(); } //注意:此时 T 与 TT 所占空间大小相同 T b; b.f(); //调用T::f(); b.~T(); new(&b)TT; //在 T 与 TT 所占空间相同时才不会报错 b.f(); //编译器仍然调用 T::f(),而不是TT::f()
- 6.2 new 和 delete 运算符
- new和delete运算符
- new和delete运算符
- new和delete运算符
- new 和 delete 运算符
- 重载new和delete运算符
- 运算符new和delete的重载
- 重载new和delete运算符
- 重载运算符new和delete
- 【C++】new和delete运算符
- 重载 new 和 delete 运算符
- new delete运算符
- new delete操作运算符
- 重载new/delete运算符
- 重载new/delete运算符
- new,delete运算符重载
- malloc() free()函数 和 new delete运算符的区别
- new运算符,delete运算符
- MySQL的管理,包括新建账户、基本信息查看
- POJ 题目 3693 Maximum repetition substring(后缀数组+RMQ+枚举求最小字典序的重复次数最多的子串)
- java.sql.SQLException: Incorrect string value: '\xE9\x99\xB6\xE4\xBC\x9F...' for column 'name' at ro
- 【Leetcode】Rotate Image
- Item 12:完整地拷贝对象(拷贝构造函数、复制运算符) Effective C++笔记
- 6.2 new 和 delete 运算符
- css的中英文对齐
- noip2001 car的旅行路线 (floyd求解最短路径长度)
- ImageView全屏
- linker command failed
- Item 13:使用对象(智能指针)来管理资源 Effective C++笔记
- MongoDB Query 的几个方法
- Android反编译工具及用法
- hdoj 2602 Bone Collector【0-1背包】【dp思想】