没有合适的资源?快使用搜索试试~ 我知道了~
首页c语言中new_C++的new归纳详解
资源详情
资源评论
资源推荐
c 语言 new:C++的 new
“new”是 C++的一个关键字,同时也是操作符。关于 new 的话题非常多,因
为它确实比较复杂,也非常神秘,下面我将把我了解到的与 new 有关的内容做
一个总结。
new 的过程
当我们使用关键字 new 在堆上动态创建一个对象时,它实际上做了三件事:获
得一块内存空间、调用构造函数、返回正确的指针。当然,如果我们创建的是
简单类型的变量,那么第二步会被省略。假如我们定义了如下一个类 A:
class A
{
int i;
public:
A(int _i) :i(_i*_i) {}
void Say() { printf("i=%dn", i); }
};
//调用 new:
A* pa = new A(3);
那么上述动态创建一个对象的过程大致相当于以下三句话(只是大致上):
A* pa = (A*)malloc(sizeof(A));
pa->A::A(3);
return pa;
虽然从效果上看,这三句话也得到了一个有效的指向堆上的 A 对象的指针 pa,
但区别在于,当 malloc 失败时,它不会调用分配内存失败处理程序
new_handler,而使用 new 的话会的。因此我们还是要尽可能的使用 new,
除非有一些特殊的需求。
new 的三种形态
到目前为止,本文所提到的 new 都是指的“new operator”或称为“new
expression”,但事实上在 C++中一提到 new,至少可能代表以下三种含义:
new operator、operator new、placement new。
new operator 就是我们平时所使用的 new,其行为就是前面所说的三个步骤,
我们不能更改它。但具体到某一步骤中的行为,如果它不满足我们的具体要求
时,我们是有可能更改它的。三个步骤中最后一步只是简单的做一个指针的类
型转换,没什么可说的,并且在编译出的代码中也并不需要这种转换,只是人
为的认识 罢了。但前两步就有些内容了。
new operator 的第一步分配内存实际上是通过调用 operator new 来完成的,
这里的 new 实际上是像加减乘除一样的操作符,因此也是可以重载的。
operator new 默认情况下首先调用分配内存的代码,尝试得到一段堆上的空
间,如果成功就返回,如果失败,则转而去调用一个 new_hander,然后继续
重复前面 过程。如果我们对这个过程不满意,就可以重载 operator new,来
设置我们希望的行为。例如:
class A
{
public:
void* operator new(size_t size)
{
printf("operator new calledn");
return ::operator new(size);
}
};
A* a = new A();
这里通过::operator new 调用了原有的全局的 new,实现了在分配内存之前
输出一句话。全局的 operator new 也是可以重载的,但这样一来就不能再递
归的使用 new 来分配内存,而只能使用 malloc 了:
void* operator new(size_t size)
{
printf("global newn");
return malloc(size);
}
相应的,delete 也有 delete operator 和 operator delete 之分,后者也是
可以重载的。并且,如果重载了 operator new,就应该也相应的重载
operator delete,这是良好的编程习惯。
new 的第三种形态——placement new 是用来实现定位构造的,因此可以实
现 new operator 三步操作中的第二步,也就是在取得了一块可以容纳指定类
型对象的内存后,在这块内存上构造一个对象,这有点类似于前面代码中的“p-
>A::A(3);”这句话,但这并不是一个标准的写法,正确的写法是使用
placement new:
#include <new.h>
void main()
{
char s[sizeof(A)];
A* p = (A*)s;
new(p) A(3); //p->A::A(3);
p->Say();
}
对头文件<new>或<new.h>的引用是必须的,这样才 可以使用 placement
new。这里“new(p) A(3)”这种奇怪的写法便是 placement new 了,它实现
了在指定内存地址上用指定类型的构造函数来构造一个对象的功能,后面 A(3)
就是对构造函数的显式调用。这里不难发现,这块指定的地址既 可以是栈,又
可以是堆,placement 对此不加区分。但是,除非特别必要,不要直接使用
placement new ,这毕竟不是用来构造对象的正式写法,只不过是 new
operator 的一个步骤而已。使用 new operator 地编译器会自动生成对
placement new 的调用的代码,因此也会相应的生成使用 delete 时调用析构
函数的代码。如果是像上面那样在栈上使用了 placement new,则必须手工
调用析构函数,这也是显式调用析构函数的唯一情况:
p->~A();
当我们觉得默认的 new operator 对内存的管理不能满足我们的需要,而希望
自己手工的管理内存时,placement new 就有用了。STL 中的 allocator 就
使用了这种方式,借助 placement new 来实现更灵活有效的内存管理。
处理内存分配异常
正如前面所说,operator new 的默认行为是请求分配内存,如果成功则返回
此内存地址,如果失败则调用一个 new_handler,然后再重复此过程。于是,
想要从 operator new 的执行过程中返回,则必然需要满足下列条件之一:
l 分配内存成功
l new_handler 中抛出 bad_alloc 异常
l new_handler 中调用 exit()或类似的函数,使程序结束
于是,我们可以假设默认情况下 operator new 的行为是这样的:
void* operator new(size_t size)
{
void* p = null
while(!(p = malloc(size)))
{
if(null == new_handler)
throw bad_alloc();
try
{
new_handler();
}
catch(bad_alloc e)
{
throw e;
剩余11页未读,继续阅读
amchuan
- 粉丝: 0
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 收起
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
会员权益专享
最新资源
- ExcelVBA中的Range和Cells用法说明.pdf
- 基于单片机的电梯控制模型设计.doc
- 主成分分析和因子分析.pptx
- 共享笔记服务系统论文.doc
- 基于数据治理体系的数据中台实践分享.pptx
- 变压器的铭牌和额定值.pptx
- 计算机网络课程设计报告--用winsock设计Ping应用程序.doc
- 高电压技术课件:第03章 液体和固体介质的电气特性.pdf
- Oracle商务智能精华介绍.pptx
- 基于单片机的输液滴速控制系统设计文档.doc
- dw考试题 5套.pdf
- 学生档案管理系统详细设计说明书.doc
- 操作系统PPT课件.pptx
- 智慧路边停车管理系统方案.pptx
- 【企业内控系列】企业内部控制之人力资源管理控制(17页).doc
- 温度传感器分类与特点.pptx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0