进一步了解new操作符

我们又了解new多少呢?

关于new操作符,我们在对空间的请求(对于类来说)上一共进行两步:

对于new:先进行空间分配,再进行调用构造函数。

在new与delete中的第二步,实际上都是调用一个全局函数operator new/delete对空间进行分配/回收。

在这个全局构造函数中::operator new 有6个重载,其中有三个是关于数组空间的分配。

如下:

void *operator new(std::size_t count) throw(std::bad_alloc);               // 一般的版本

void *operator new(std::size_t count,new const std::nothrow_t&) throw();   // 内存分配失败不会抛出异常

void *operator new(std::size_t count, void *ptr) throw();  <span style="white-space:pre">		</span>   //placement 版本         <span style="font-family: Arial, Helvetica, sans-serif;">                           </span>
void *operator new[](std::size_t count)  throw(std::bad_alloc);

void *operator new[](std::size_t count, const std::nothrow_t&) throw();

void *operator new[](std::size_t count, void *ptr) throw();
 

对于一般版本,为了兼容早期new而不抛出异常的版本 ,我们已经用的很熟练了,我们只谈一谈placment new 版本。

区分new 操作符与operator new 函数是十分重要的,对于new操作符,我们不可以重载所以new操作符的行为是确定的,而operator new是可以进行重载的,对其进行替换的 。但对于placement new 版本,在c++标准中已经明令禁止我们去重载这个版本,对于其它版本我们可以任意的去替换掉(说是这么说但实际上并不赞同这样做)。

为什么c++严禁我们去重载这个placement new 这个函数呢,palcement new 与其它重载版本不同它实际上并不会分配任何空间,仅仅返回一个可能指向空间的指针。

因此我们不能对placemen newt进行delete操作。

可能有人会问对于placement new有什么作用?

我们在创建一个对象的时候,我们可能不想给它初始化,我们希望迟一点初始化,这时候,而我们提前对它的初始化就是十分浪费效率的。

我们就可以这样做

	A *number0 = static_cast<A*>(::operator new(sizeof(A)));
	new(number0)A();
	
对于operator new(size_t);实际上与memory.h头文件中的malloch函数效果是一样的的。


通常对placement new也搭配一些其它操作,一般来说这个是必要的,我们必须对一个类对象进行析构,不过直接对一个对象进行析构十分不妥的,我们需要对这个析构进行一下封装。


实际上,对于一个类而不是语言内嵌类型,对于一个new与delete的操作实际上是分成三步的,多了一步,我们在进行operator new 调用之前会先查找class内是否有这个operator new 的重载,如果有我们会调用class中的重载版本,有一点就算我们把operator new 声明为私有类成员,编译器也只会提示一个类成员不可调用,也不会调用全局的operator new。

我们在开始说placement new 重载是明令禁止的,但这个要求仅限于全局,我们在类中仍可以定义一个“placement new”。

还有一点,对于类内重载的operator new/delete是静态成员函数, 因为他用不到this指针。所以operator new/delete是可以被继承的,


关于数组的说明:

!只有一点

我们对于数组的分配方法

	A *number1 = static_cast<A*>(::operator new[](sizeof(A)*2));
	A *number2 = new A[2];
第二种相对于第一种可能会略微增加内存。


关于operator new我们可能面临这样一个错误,当我们无法知道一个类是否已经重载operaotr的时候,我们就面临着一个很危险的行为,我们无法准确的对这个类进行异常的判断此时我们必须将所有的operator new都使用全局版本。

一般的来说我们在重载operator new 的时候一般也会重载operator delete 如果一个类的operator new 分配失败则,这个类将调用operator delete 进行回收。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值