现在的位置: 首页 > 综合 > 正文

C++优化内存分配

2017年11月17日 ⁄ 综合 ⁄ 共 2855字 ⁄ 字号 评论关闭

C++中,在需要对象时使用new操作符,为对象分配内存并在分配的内存处初始化一个对象。

在使用new操作符时,有两步1、给对象分配内存,这时内存是未构造的2、在分配内存处运行构造函数。

在一些情况下,第2步是不需要的,或者可以推迟第2步的操作,先分配内存,在需要时,在预先分配的内存中再构造对象。例如,我们构建了一个对象,但是从来不使用,在使用时,已经给对象赋予了其他值。(在给没有对象的内存赋值时,其后果可能是灾难性的,之前在重载=运算符时就看以看到,赋值操作符是要删除左值的,如果没有左值,调用左值对象的析构函数程序崩溃)

delete操作符也是有2步,1、调用析构函数2、把对象所用内存还给系统。

在处理C++内存分配时,要解决2个问题。1、分配原始内存时,必须在内存中构造对象。2、在释放内存之前,必须适当地撤销对象。

C++提供2中方法来分配和释放未构造的原始内存。1、allocator类。2、operator new和operator delete。

C++也提供了不同的方法在原始内存中构造和撤销对象

1、allocator类的成员函数construct在未构造的内存中初始化对象,成员函数destroy在对象上运行析构函数。

2、定位new表达式,它接受之前未构造的内存的指针,在该内存中初始化对象或数组。

3、直接调用对象的构造、析构函数。运行析构函数并不是释放对象所占用内存,只是销毁对象。

4、算法uninitilalized_fill和uninitialized_copy


allocator类是一个类模板,它可以提供类型化内存分配和对象的构造与撤销

allocator<T> a;//a为allocator对象,处理T类型内存
a.allocate(n);//分配n*sizeof(T)大小的未构造的内存
a.deallocate(p,n);//释放内存n*sizeof(T),p为指向内存对象,并不运行析构函数
a.construct(p,t);//在指针p处构造对象,运行T类型的复制构造函数,用t初始化
a.destroy(p);//运行p指针处对象的析构函数

更多关于allocator的资料,参考这里:http://www.cplusplus.com/reference/memory/allocator/


operator new函数和operator delete函数

这与操作符new和delete不同。operator new函数只是分配内存,operator delete只是销毁对象。

operator new函数有2个版本

void *operator new(size_t );//分配一个对象内存

void *operator new[](size_t);//分配一个数组内存

注意,上面函数返回的是void*指针,这个有点像malloc函数,在使用前要进行指针类型转换。

同理,operator delete函数也有2个版本

void *operator delete(void* );//释放对象

void *operator delete[](void *);//释放数组

有点像allocator的deallocate函数,但是delete函数是在void*指针上操作的。注意,operator delete函数并不运行析构函数,如果需要可以显示调用析构函数


定位new表达式

定位new表达式是用来在已分配的内存上初始化对象的,它并不分配内存。使用方法如下:

new (p) type;//在指针p处构造type类型对象

new (p) type(initializer list);//在指针p处用初始化列表构造对象。

 

可以结合《STL源码剖析》”2.1-设计一个简单的空间配置器“来学习一下,使用operator new和operator delete以及定位new来实现allocator类。

#ifndef _JJALLOC_
#define _JJALLOC_
#include<new>
#include<cstddef>
#include<cstdlib>
#include<climits>
#include<iostream>

namespace JJ
{
	template<class T>
	inline T* _allocate(ptrdiff_t size, T*){//分配内存,但不初始化
		std::set_new_handler(0);
		T* tmp=(T*)(::operator new((size_t)(size*sizeof(T))));
		if(tmp==0){
			std::cerr<<"out of memory"<<std::endl;
			exit(1);
		}
		return tmp;
	}
	
	template<class T>
	inline void _deallocate(T* buffer){//释放内存
		::operator delete(buffer);
	}
	
	template<class T1, class T2>
	inline void _construct(T1* p, const T2& value){
		new(p) T1(value);//定位new
	}
	
	template<class T>
	inline void _destroy(T* ptr){
		ptr->~T();//显示调用析构函数
	}
	
	template<class T>
	class allocator{
		public:
			typedef T value_type;
			typedef T* pointer;
			typedef const T* const_pointer;
			typedef T& reference;
			typedef const T& const_reference;
			typedef size_t size_type;
			typedef ptrdiff_t difference_type;//两个指针的差
			
			template<class U>
			struct rebind{
				typedef allocator<U> other;
			};
			
			pointer allocate(size_type n, const void* hint=0)
			{
				return _allocate((difference_type)n, (pointer)0);
			}
			
			void deallocate(pointer p, size_type n)
			{
				_deallocate(p);
			}
			
			void construct(pointer p, const T& value)
			{
				_construct(p,value);
			}
			
			void destroy(pointer p)
			{
				_destroy(p);
			}
			
			pointer address(reference x)
			{
				return (pointer)&x;
			}
			
			const_pointer const_address(const_reference x)
			{
				return (const_pointer)&x;
			}
			
			size_type max_size()const
			{
				return size_type(INT_MAX*2/sizeof(T));//使用UNIT_MAX时编译出错
			}
		};
}

#endif

 

 

抱歉!评论已关闭.