C++内存管理(未完...)

本文代码中出现的类 

class Complex{
	public:
		int num;
		Complex(int _num) : num(_num){}
		Complex(){}
		~Complex(){}
};

 

四种常用内存申请方式 


	//--------四种内存申请方式----------
	void* p1 = malloc(512);          //申请512bytes
	free(p1);
	
	string* p2 = new string;         //申请one object
	delete p2;
	
	void* p3 = ::operator new(512);  //申请512bytes
	::operator delete(p3);
	
	
	int* p4 = allocator<int>().allocate(5); //分配5个int
	//int* p4 = allocator<int>().allocate(5, (int*)0); //同上,但是(int*)0并没有必要
	allocator<int>().deallocate(p4, 5);

new、delete的解析


	//---------------new的解析---------------------
	//Complex* cp = new Complex();
	
	//new的实现过程 
	Complex* cp;
	try{
		void* men = operator new(sizeof(Complex));
		cp = static_cast<Complex*>(men);
		//编译器执行为 cp->Complex::Complex(5); 但是我们只能写作如下: 
		new(cp)Complex(5);
	}catch(std::bad_alloc){
		
	}
	cout << cp->num << endl;
	
	//-----------delete的解析--------------------
	//delete cp;
	cp->~Complex();
	operator delete(cp);        //free(cp); 

 Array new


	//-----------Array new--------------
	Complex* cp = new Complex[7];
	//----------Array delete------------
	delete[] cp;

 初始化Arry

class A{
	public:
		int id;
		A() : id(0){ cout << "default ctor.this=" << this << "  id=" << id << endl; }
		A(int i) : id(i){ cout << "ctor.this=" << this << "  id=" << id << endl; }
		~A(){ cout << "ctor.this=" << this << "  id=" << id << endl; }
}; 

 

//-----------初始化一个array----------------- 
	const int size = 3;
	A* buf = new A[size];
	A* temp = buf;
	cout << "buf = " << buf <<" temp = " << temp << endl;
	
	for(int i  = 0; i < size; i++ ){
		new(temp++)A(i);
	}
	
	cout << "buf = " << buf << " temp = " << temp << endl;
	
	delete[] buf;

 基本数据类型的Array new

//-------------------int类型的array new------------------
	int *p = new int[5];
	delete p;            //由于p是int类型,它没有有意义的析构函数,所以这里使用delete与delete[]是一样的 

placement new(定位new)

//placement new允许将对象创建于一个已经分配的内纯中,所以要有一个指针代表已经分配好的内存
	char* buf = new char[sizeof(Complex)*3]; //buf指针指向的就是提前分配好的内存 
	Complex* cp = new(buf)Complex();        //将pc创建在buf上,这样pc就不会重新分配内存 
	//Complex* cp = new(buf)Complex()也可写作如下 
	//Complex* cp;
	//try{
	//	void* men = operator new(sizeof(Complex), buf); //placement new
	//	cp = static_cast<Complex*>(men);
	//	cp->Complex::Complex();  //只有编译器可以这样做,所以这句我们使用时会报错 
	//}catch(std::bad_alloc){
	//	
	//}
	delete[] buf; //没有placement delete因为placement new根本没有分配内存 

 重载::operator new、::operator delete(不建议这样做)

不建议这样做,全局new与delete被重载的话影响无穷无尽。 

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

class Complex{
	public:
		int num;
		Complex(int _num) : num(_num){}
		Complex(){}
		~Complex(){}
};
void* myAlloc(size_t size){
	return malloc(size);
}
inline void* operator new(size_t size){
	cout << "调用了自己重载的new" << endl;
	return myAlloc(size);
} 

inline void* operator new[](size_t size){
	cout << "调用了自己重载的new" << endl;
	return myAlloc(size);
} 

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

inline void operator delete(void* ptr){
	cout << "调用了自己重载的delete" << endl;
	myFree(ptr); 
}

inline void operator delete[](void* ptr){
	cout << "调用了自己重载的delete" << endl;
	myFree(ptr); 
}
int main(){
	//----------------重载new--------------------
	Complex* cp;								//这一步cp并没有指向 
	void* men = operator new(sizeof(Complex));
	cp = static_cast<Complex*>(men);			//这里cp指向了men开辟的内存 
	new(cp)Complex(5);							//在内存上建立对象 
	
	cout << cp->num << endl;
	
	operator delete(cp);
	return 0;
}

重载类的operator new、operator delete

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

class Foo{
	public:
		Foo(){}
		~Foo(){}
		
		void* operator new(size_t size){
			Foo *f = (Foo*)malloc(size);
			cout << "调用了自己重载的new" << endl;
			return f;
		} 
		void* operator new[](size_t size){
			Foo *f = (Foo*)malloc(size);
			cout << "调用了自己重载的new" << endl;
			return f;
		}
		
		void operator delete(void* ptr){
			cout << "调用了自己重载的delete" << endl; 
			free(ptr);
		}

		void operator delete[](void* ptr){
			cout << "调用了自己重载的delete" << endl;
			free(ptr);
		}
};


int main(){
	Foo* foo = new Foo[5];
	delete[] foo;
	return 0;
}

重载placement new

 

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

class Foo{
	public:
		int id;
		Foo(int i) : id(i){}
		Foo(){}
		~Foo(){}
		
		void* operator new(size_t size){
			Foo *f = (Foo*)malloc(size);
			cout << "operator new(size_t size)" << endl;
			return f;
		} 
		
		void* operator new(size_t size, void* start){
			cout << "operator new(size_t size, void* start)" << endl;
			return start;
		} 
		
		
		void* operator new(size_t size, long ers){
			cout << "operator new(size_t size, long ers)" << endl;
			return malloc(size + ers);
		} 
		
		void* operator new(size_t size, long ers, char ch){
			cout << "operator new(size_t size, long ers, char ch)" << endl;
			return malloc(size + ers);
		} 
		
		
		void* operator new[](size_t size){
			Foo *f = (Foo*)malloc(size);
			cout << "operator new[](size_t size)" << endl;
			return f;
		}
		
		void operator delete(void* ptr){
			cout << "operator delete(void* ptr)" << endl; 
			free(ptr);
		}
		
		void operator delete(void* ptr, long ers){
			cout << "operator delete(void* ptr, long ers)" << endl; 
			free(ptr);
		}
		
		void operator delete(void* ptr, long ers, char ch){
			cout << "operator delete(void* ptr, long ers)" << endl; 
			free(ptr);
		}

		void operator delete[](void* ptr){
			cout << "operator delete[](void* ptr)" << endl;
			free(ptr);
		}
};


int main(){
	Foo start;
	
	Foo* f1 = new(&start)Foo;
	Foo* f2 = new(100)Foo;
	Foo* f3 = new(100)Foo(2);
	Foo* f4 = new(100,'c')Foo;
	cout << start.id;
	return 0;
}

在重载placement new时,第一参数必须是size_t类型,并且最好写上其对应的重载delete.

 

简单内存池

#include <iostream>
#include <thread>
#include <cstddef> 
using namespace std;

class Screen{
public:
	Screen(int _i) : i(_i){	}
	int get(){ return i; }
	
	void* operator new(size_t);
	void operator delete(void*, size_t);
	
private:
	Screen* next;
	static Screen* freeStore;
	static const int screenChunk;

private:
	int i;
};

Screen* Screen::freeStore = 0;
const int Screen::screenChunk = 24;

void* Screen::operator new(size_t size){
	Screen*p;
	if(!freeStore){
		//内存池为空,申请一大堆
		size_t chunk = screenChunk * size;
		freeStore = p = reinterpret_cast<Screen*>(new char[chunk]);
		
		//将内存池分割
		for(; p != &freeStore[screenChunk-1]; ++p)
			p->next = p + 1;
		
		p->next = 0;
	}
	
	p = freeStore;
	freeStore = freeStore->next;
	
	return p;
} 

void Screen::operator delete(void* p, size_t){
	(static_cast<Screen*>(p))->next = freeStore;
	freeStore = static_cast<Screen*>(p);
}

int main(int argc, char** argv) {
	
	cout << "sizeof(Screen) = " << sizeof(Screen) << endl;
	
	size_t const N = 100;
	
	Screen* p[N];
	
	for(int i = 0; i < N; ++i)
		p[i] = new Screen(i);
		
	for(int i = 0; i < 10; ++i)
		cout << p[i] << endl;
		
	for(int i = 0; i < N; ++i)
		delete p[i];
	
	return 0;
}

测试结果发现,分配的内存为连续空间,并且大小为16

 

 

如果不使用内存池

#include <iostream>
#include <thread>
#include <cstddef> 
using namespace std;

class Screen{
public:
	Screen(int _i) : i(_i){	}
	int get(){ return i; }

private:
	int i;
};

int main(int argc, char** argv) {
	
	cout << "sizeof(Screen) = " << sizeof(Screen) << endl;
	
	size_t const N = 100;
	
	Screen* p[N];
	
	for(int i = 0; i < N; ++i)
		p[i] = new Screen(i);
		
	for(int i = 0; i < 10; ++i)
		cout << p[i] << endl;
		
	for(int i = 0; i < N; ++i)
		delete p[i];
	
	return 0;
}

虽然类的大小变小了,但是数组每个却占用了32个字节

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值