C++内存管理11 重载new()和delete()/下

Foo* pf=new(300,'c') Foo;

这个叫placement new但不定点。
重载时第一个参数必须是size_t
因为正常new Foo时会把Foo大小传给operator new

1.重载new()

class Foo
{
public:
  	Foo() { cout << "Foo::Foo()" << endl;  }
  	Foo(int) { 
	   			cout << "Foo::Foo(int)" << endl;  
	           	// throw Bad();  
			 }

  	//(1) 這個就是一般的 operator new() 的重載 
  	void* operator new(size_t size) {
		cout << "operator new(size_t size), size= " << size << endl;
    	return malloc(size);  
  	}

  	//(2) 這個就是標準庫已經提供的 placement new() 的重載 (形式)
	//    (所以我也模擬 standard placement new 的動作, just return ptr) 
  	void* operator new(size_t size, void* start) { 
	  	cout << "operator new(size_t size, void* start), size= " << size << "  start= " << start << endl;
    	return start;
  	}

  	//(3) 這個才是嶄新的 placement new 
  	void* operator new(size_t size, long extra) { 
	  	cout << "operator new(size_t size, long extra)  " << size << ' ' << extra << endl;
    	return malloc(size+extra);
  	}

  	//(4) 這又是一個 placement new 
  	void* operator new(size_t size, long extra, char init) { 
	  	cout << "operator new(size_t size, long extra, char init)  " << size << ' ' << extra << ' ' << init << endl;
    	return malloc(size+extra);
  	}
  	//(5) 這又是一個 placement new, 但故意寫錯第一參數的 type (它必須是 size_t 以滿足正常的 operator new) 
  	//这里会报错
//!  	void* operator new(long extra, char init) { //[Error] 'operator new' takes type 'size_t' ('unsigned int') as first parameter [-fpermissive]
//!	  	cout << "op-new(long,char)" << endl;
//!    	return malloc(extra);
//!  	} 	

2.重载delete()

//搭配上述placement new的placement delete
void operator delete(void*,size_t)
  	{ cout << "operator delete(void*,size_t)  " << endl;  }

	//(2) 這是對應上述的 (2)  
  	void operator delete(void*,void*)
  	{ cout << "operator delete(void*,void*)  " << endl;  }

	//(3) 這是對應上述的 (3)  
  	void operator delete(void*,long)
  	{ cout << "operator delete(void*,long)  " << endl;  }

	//(4) 這是對應上述的 (4)  
	//如果沒有一一對應, 也不會有任何編譯報錯 
  	void operator delete(void*,long,char)
  	{ cout << "operator delete(void*,long,char)  " << endl; }
  	

test代码:

void test_overload_placement_new()
{
	cout << "\n\n\ntest_overload_placement_new().......... \n";
	
  	Foo start;  //Foo::Foo

  	Foo* p1 = new Foo;           //op-new(size_t)
  	Foo* p2 = new (&start) Foo;  //op-new(size_t,void*)
  	Foo* p3 = new (100) Foo;     //op-new(size_t,long)
  	Foo* p4 = new (100,'a') Foo; //op-new(size_t,long,char)
	//带括号的new不是一般的placement new所以调用第3个重载的operator new
	//new(100)的100是extra,size是4因为私有一个int成员。
  	Foo* p5 = new (100) Foo(1);     //op-new(size_t,long)  op-del(void*,long)
  	
  	Foo* p6 = new (100,'a') Foo(1); //
  	Foo* p7 = new (&start) Foo(1);  //
  	Foo* p8 = new Foo(1);           //
  	//VC6 warning C4291: 'void *__cdecl Foo::operator new(unsigned int)'
  	//no matching operator delete found; memory will not be freed if
  	//initialization throws an exception
}

运行结果:
在这里插入图片描述

最后附上完整代码:

#include <cstddef>
#include <iostream>
#include <vector>  //for test
using namespace std;
namespace jj07
{

class Bad { };
class Foo
{
public:
  	Foo() { cout << "Foo::Foo()" << endl;  }
  	Foo(int) { 
	   			cout << "Foo::Foo(int)" << endl;  
	           	// throw Bad();  
			 }

  	//(1) 這個就是一般的 operator new() 的重載 
  	void* operator new(size_t size) {
		cout << "operator new(size_t size), size= " << size << endl;
    	return malloc(size);  
  	}

  	//(2) 這個就是標準庫已經提供的 placement new() 的重載 (形式)
	//    (所以我也模擬 standard placement new 的動作, just return ptr) 
  	void* operator new(size_t size, void* start) { 
	  	cout << "operator new(size_t size, void* start), size= " << size << "  start= " << start << endl;
    	return start;
  	}

  	//(3) 這個才是嶄新的 placement new 
  	void* operator new(size_t size, long extra) { 
	  	cout << "operator new(size_t size, long extra)  " << size << ' ' << extra << endl;
    	return malloc(size+extra);
  	}

  	//(4) 這又是一個 placement new 
  	void* operator new(size_t size, long extra, char init) { 
	  	cout << "operator new(size_t size, long extra, char init)  " << size << ' ' << extra << ' ' << init << endl;
    	return malloc(size+extra);
  	}
  	
   	//(5) 這又是一個 placement new, 但故意寫錯第一參數的 type (它必須是 size_t 以滿足正常的 operator new) 
//!  	void* operator new(long extra, char init) { //[Error] 'operator new' takes type 'size_t' ('unsigned int') as first parameter [-fpermissive]
//!	  	cout << "op-new(long,char)" << endl;
//!    	return malloc(extra);
//!  	} 	

    //以下是搭配上述 placement new 的各個 called placement delete. 
	//當 ctor 發出異常,這兒對應的 operator (placement) delete 就會被喚起. 
	//應該是要負責釋放其搭檔兄弟 (placement new) 分配所得的 memory.  
  	//(1) 這個就是一般的 operator delete() 的重載 
  	void operator delete(void*,size_t)
  	{ cout << "operator delete(void*,size_t)  " << endl;  }

	//(2) 這是對應上述的 (2)  
  	void operator delete(void*,void*)
  	{ cout << "operator delete(void*,void*)  " << endl;  }

	//(3) 這是對應上述的 (3)  
  	void operator delete(void*,long)
  	{ cout << "operator delete(void*,long)  " << endl;  }

	//(4) 這是對應上述的 (4)  
	//如果沒有一一對應, 也不會有任何編譯報錯 
  	void operator delete(void*,long,char)
  	{ cout << "operator delete(void*,long,char)  " << endl; }
  	
private:
  	int m_i;
};


//-------------	
void test_overload_placement_new()
{
	cout << "\n\n\ntest_overload_placement_new().......... \n";
	
  	Foo start;  //Foo::Foo

  	Foo* p1 = new Foo;           //op-new(size_t)
  	Foo* p2 = new (&start) Foo;  //op-new(size_t,void*)
  	Foo* p3 = new (100) Foo;     //op-new(size_t,long)
  	Foo* p4 = new (100,'a') Foo; //op-new(size_t,long,char)

  	Foo* p5 = new (100) Foo(1);     //op-new(size_t,long)  op-del(void*,long)
  	Foo* p6 = new (100,'a') Foo(1); //
  	Foo* p7 = new (&start) Foo(1);  //
  	Foo* p8 = new Foo(1);           //
  	//VC6 warning C4291: 'void *__cdecl Foo::operator new(unsigned int)'
  	//no matching operator delete found; memory will not be freed if
  	//initialization throws an exception
}
} //namespace	
int main(){
    jj07::test_overload_placement_new();
    return 0;
}

如果存在Bad(),抛出异常,当placement new调用到这个函数时,即调用相应的delete()进行释放,目的是为了防止内存分配好了后对象建立不起来,写出抛出异常可以进行释放。

  	Foo(int) { 
	   			cout << "Foo::Foo(int)" << endl;  
	           	throw Bad();//这句起作用  
			 }

运行结果如下:
在这里插入图片描述
即使new()和delete()没有一一对应,也不会报错。你的意思是放弃处理构造函数发出的异常。

例子:

平时用的string是一个type define 的basic_string
在这里插入图片描述

每创建一个字符多一个extra。

以上来自侯捷老师视频仅用于学习。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值