条款52:写了placement new 也要写Placement delete

/*条款52:写了placement new 也要写Placement delete*/
#include<iostream>
using namespace std;
//class Widget {};
class Widget {
public:
	//..
	static void*operator new(std::size_t size, std::ostream&logStream)throw(std::bad_alloc);//非正常形式的new
	static void*operator delete(void* pMemory std::size_t size)throw();//正常的class专属delete
	// placement new :如果在operator接受的参数除了一定会有的那个size_t之外还有其他,这个便是所谓的placement new
	//一个比较常用的 placement new 接受一个指针指向对象该被构造之处如下:
	// void*operator new(std::size_t ,void*pMemory)throw(); 这个版本的new已被纳入C++标准程序库,头文件#include<new>,它的用途之一是负责在vector的未使用空间上创建对象,实际上它正是这个函数的命名根据:一个特定位置的new,上下文语境往往也能够使意义不明确的含糊话语清晰起来
	//如果没有与上面对象的operator delete 就无法对内存分配动作做恢复所以要加上下面的内容
	static void operator delete (void*pMemory)throw();//如果没有发生异常,则调用对应的delete
	static void operator delete(void*pMemory, std::ostream&logStream)throw();
};//但这里有一个名字掩盖的问题 调用时要传递对应的参数,第二是子类可能有名字相同的函数把基类new掩盖掉
/---------------------上述出现 的掩盖的问题可以像如下方式去解决
class StandardNewDeleteForms {
public:
	//正常的new/delete
	static void* operator new(std::size_t size)throw(std::bad_alloc){
		return ::operator new(size);
	}
	static void operator delete(void* pMemory)throw() {
		::operator delete(pMemory);
	}
	// placement new/delete
	static void*operator new(std::size_t size, void*ptr)throw(){
		return ::new_handler(size,ptr);
	}
	static void operator delete(void*pMemory, void*ptr)throw() {
		return ::operator delete (pMemory, ptr);
	}
	//nothrow new/delete
	static void*operator new (std::size_t size, const std::nothrow_t&nt)throw(){
		return ::operator new(size,nt);
	}
		static void operator delete (void *pMemory, const std::nothrow_t &)throw() {
		::operator delete(pMemory);
	}
};
//凡是想以自定形式扩充标准形式的客户,可利用继承机制及using 声明式取得标准形式
class Widget :public StandardNewDeleteForms {
public:
	using StandardNewDeleteForms::operator new;//继承标准形式,让这些形式可见
	using StandardNewDeleteForms::operator delete;
	static void*operator new(std::size_t size, std::ostream&logStream)throw(std::bad_alloc);
	static void operator delete(void*pMemory, std::ostream&logSteam)throw();//添加一个自定的placement delete
	//..
};
int main() {
	Widget*pw = new Widget;//这个表达式调用了两个函数,1 operator new 2 Widget的default构造函数
	//假设第一个调用成功,第二个函数却抛出异常,那么步骤一的内存分配所得必须取消并恢复旧观,否则就是内存漏洞,并且客户手上没有指针指向被归还的内存,取消步骤一就落到了C++运行期系统身上了
	Widget *pw1 = new (std::cerr)Widget;//调用operator new 并传递cerr为ostream实参,这个动作会在Widget构造函数抛出异常时泄漏内存
	// 这里的问题是如果内存分配成功,而Widget构造函数抛出异常,运行期系统有责任取消opeator new 的分配并恢复旧观,然而运行期系统无法知道真正被调用的那个operator new 如何动作,因此无法取消分配并恢复旧观,那么我们可以根据上面的new找出对应的operator delete
	// void operaotr(void*,std::ostream&)throw();
	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值