c++之 new expression

new 一个对象发生了什么?

1、new对象发生的事情

Complex *pc = new Complex(2,4);

当编译器看到上边代码时会做出以下动作:

Complex *pc;
try{
	void *mem = operator new(sizeof(Complex));//先分配内存空间
	pc = static_cast<Complex*>(mem);//指针转型
	pc->Complex::Complex(2,4)//在调用构造函数
}//
delete pc

编译器转为以下做法:

pc->~Complex()//先析构对象
operator delete(pc)//释放内存

看到编译器的操作,我们不仅想自己模仿一下编译器的操作:
我们可以这样做模拟操作系统的做法:

#include<iostream>
#include<string>
#include<memory>
using namespace std;
class A {
public:
	int id;
	A(int i) :id(i) {
		cout << "ctor.this=" << this << "id=" << id << endl;
	}
	~A() {
		cout << "dtor.this=" << this << endl;
	}
};
int main() {
	A* pA = new A(1);
	cout << pA->id << endl;
	pA->A::A(3);
	cout << pA->id << endl;
	pA->A::~A();
}

输出结果:
在这里插入图片描述

new 对象怎样发生的?

在这里插入图片描述

重载 ::operator new / :: operator delete(这个要小心使用)

#include<iostream>
#include<string>
#include<memory>
using namespace std;

void* myAlloc(size_t  size){//模仿全局的 
	return malloc(size);
} 

void myFree(void* ptr){
	return free(ptr);
}

inline void* operator new (size_t size){
	cout <<"全局的new() \n";
	return myAlloc(size);
}

inline void operator delete(void *ptr){
	cout <<"全局的delete() \n";
	return myFree(ptr);

} 

class Foo{
public:
	Foo(){
		cout << "ctor chenggong \n";
	}
	~Foo(){
		cout << "dtor chenggong \n";
	}
};

int main(){
	Foo *f = new Foo();
}

在这里插入图片描述

重载类中 operator new / operator new[] / operator delete /operatpr delete[]

array new,array delete
Foo *pc = new Foo[3];//唤醒三次默认构造函数,但是无法由参数赋值
delete[] pc //唤醒三次析构函数对于没有指针的成员也可以用 delete pc;具体原因如下图

在这里插入图片描述

#include<iostream>
#include<string>
#include<memory>
using namespace std;
class Foo{
public:
	int _id;
	Foo():_id(0){
		cout << "默认构造函数 this:"<< this <<"id = " << _id <<endl; 
	}
	Foo(int i):_id(i){
		cout << "构造函数 this:"<< this <<"id = " << _id <<endl; 
	}
	~Foo(){
		cout << "dtor.this"<< this << "id=" << _id << endl;
	}
	
};

int main(){
	cout <<" sizeof(Foo) ="<< sizeof(Foo) << endl;
	Foo *f = new Foo[3];
	Foo *tmp = f;
	cout << "buf=" << f << "tmp =" <<tmp << endl;
	for(int i=0;i<3;i++){
		new(tmp++)Foo(i);//调用有参数构造函数 
	}
	cout << "buf=" << f << "tmp=" <<tmp<<endl;
	delete[]f;
}

在这里插入图片描述

重载类中的operator new 和operator 可以方便我们管理管理内存
具体做法:

class Foo{
	public:
		static void *operator new(size_t size);
		static void operator delete(void* ptr,size_t size)
		static void *operator new[](size_t size);
		static void operator delete[](void* ptr,size_t size)
}

看例子:

#include<iostream>
#include<string>
#include<memory>
using namespace std;
class Foo{
public:
	int _id;
	long _data;
	string _str;
	Foo():_id(0){
		cout << "默认构造函数 this:"<< this <<"id = " << _id <<endl; 
	}
	Foo(int i):_id(i){
		cout << "构造函数 this:"<< this <<"id = " << _id <<endl; 
	}
	~Foo(){
		cout << "dtor.this"<< this << "id=" << _id << endl;
	}
	
	
	static void* operator new(size_t size);
	static void operator delete(void* ptr,size_t size);
	static void* operator new[](size_t size);
	static void operator delete[](void *ptr,size_t size);
};


void* Foo::operator new(size_t size){
	Foo *p = (Foo*)malloc(size);
	cout<<"重载之后的new";
	return p; 
}

void Foo::operator delete(void* ptr,size_t size){
	cout<<"重载之后的delete";
	free(ptr); 
}
void* Foo::operator new[](size_t size){
	Foo *p = (Foo*)malloc(size);
	cout<<"重载之后的new[]";
	return p; 
}
void Foo::operator delete[](void* ptr,size_t size){
	cout<<"重载之后的delete[]";
	free(ptr); 
}


int main(){
	cout <<" sizeof(Foo) ="<< sizeof(Foo) << endl;
	Foo *f = new Foo(7);
	delete f;
	Foo *pArray = new Foo[7];
	delete[]pArray;
}

在这里插入图片描述

重载new()/delete()

我们可以重载class member operator(),可以写出很多版本,但是每一个版本都必须拥有独特的参数列,并且第一个参数必须是size_t.出现new(args…) 这就是placement new

我们可以重载delete() 并且写出很多版本,但他们绝不会被delete,只用当new所调用的构造函数抛出exception,才会调用这些重载的delete(),只可能这样调用,主要用来归还未能完全创建成功的对象所占用的内存
例子:

#include<iostream>
#include<string>
#include<memory>
#include<exception>
using namespace std;

class Bad{
};
class Foo{
	int _i;
public:

	Foo(){
		cout << "默认构造函数 this:"<< this <<endl; 
	}
	Foo(int i):_i(i){
		cout << "构造函数 this:"<< this  <<endl; 
		throw Bad();//抛出异常,测试delete(); 
	}
	
	//1、一般的operator new() 的重载 
	void* operator new(size_t size)
	{
		return malloc(size);
	}
	//2、这个是标准库已经提供的placement new() 的重载形式,模拟一下 
	void* operator new(size_t size,void *start)
	{
		return start;
	}
	//3、新的placement new 
	void* operator new(size_t size,long extra)
	{
		return malloc(size+extra);
	}
	//4、又一个新的placement new 
	void* operator new(size_t size,long extra,char init)
	{
		return malloc(size+extra);
	}
	//对用版本1的 
	void operator delete(void*,size_t){
		cout << "operator delete(void*,size_t)" <<endl; 
	}
		//对用版本2的 
	void operator delete(void*,void*){
		cout << "operator delete(void*,void*)" <<endl; 
	}
		//对用版本3的 
	void operator delete(void*,long){
		cout << "operator delete(void*,long)" <<endl; 
	}
		//对用版本4的 
	void operator delete(void*,long,char){
		cout << "operator delete(void*,long,char)" <<endl; 
	}
	
};

int main(){
	cout <<" Foo start ="<<endl;
	Foo start;
	Foo *p1= new Foo;
	Foo *p2= new(&start) Foo;
	Foo *p3= new(100) Foo;
	Foo *p4= new(100,'a')Foo;
	Foo *p5= new(100)Foo(1);
	Foo *p6= new(100,'a') Foo(1);
	Foo *p7= new(&start)Foo(1);
	Foo *p8= new Foo(1);
}

在这里插入图片描述出现异常的时候没有调用operator delete(void*,long)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值