Chapter 29.优化内存分配

来源:互联网 发布:js. bind 编辑:程序博客网 时间:2024/06/03 12:52

 简介

C++中,内存分配和对象构造是一起的(new所做的工作就是为特定类型分配内存,并在新分配的内存中构造该类型的一个对象 ),但我们有时想自己管理内存分配、对象构造,即把内存分配和对象构造分离开来

eg:

如stl中vector会预分配一定额外内存,但不进行构造,因为对没有使用的内存构造对象是很浪费的,可能用永远不使用这部分额外的内存,所以内存分配和对象构造有时就需要分离开来

allocator类模板简介

在vs2010中allocator类模板和uninitialized_copy/fill/fill_n都包含在#include <memory>头文件中

allocator<T> a;//这个还明显就是定义一个a的allocator<T>的对象,用来分配原始内存、构造T类型的对象

a.allocate(n);//分配原始内存以保存n个T类型的对象

a.construct(p,t);//在名为p的T*指针处构造一个T类型对象t,使用的是复制构造函数

a.destroy(p);//对名为p的T*指针所指对象析构

a.deallocate(p,n);//在名为p的T*指针处释放n个T类型对象的内存

uninitialized_copy/fill/fill_n简介

uninitialized_copy(b,e,b2);//把b-e这个输入范围的元素复制到b2开始的原始内存中,此算法作用是在目的地构造元素,而不是赋值

uninitialized_fill(b,e,t);//把b-e这个范围的对象初始化为t的副本

uninitialized_fill_n(b,e,t,n);//把b-e这个范围至多n个对象初始化为t的副本

分配和释放未构造的原始内存的方法

1.allocator类中的a.allocate(n)、a.deallocate(p,n)两个方法

2.operator new 和 operator delete两个标准库函数

两个方法的区别:allocator类中方法是对类型化指针的操作,而operator new/delete是对void*指针的操作

原型:

void *operator new(size_t);

void *operator new[](size_t);

void *operator delete(void*);

void *operator delete[](void*);

eg://new和delete表达式工作流程
string *sp=new string("hello");
1.调用operator new分配原始内存
2.运行string类模板的构造函数构造对象
3.返回指针向新分配并构造对象的指针
delete sp;
1.析构
2.调用operator delete释放内存

原始内存中构造和析构对象的方法

1.allocator类中的a.construct(p,t)、a.destroy(p)两个方法

2.定位new表达式,使用可以是任何构造函数,并直接建立对象

3.直接调用对象的析构函数撤销对象

4.算法uninitialized_fill和uninitialized_copy就像fill、copy算法一样构造对象

定位new表达式的作用

在特定的、预分配的内存地址(原始内存,未构造)构造一个对象

格式:

new (place_address) type;

new (place_address) type(initializer-list);

//place_address是一个指针,initializer-list是一个初始化列表

eg://与alloc.construct(p,t)的区别allocator<string> alloc;string *sp=alloc.allocate(2);//分配两个strings原始内存new (sp) string(b,e);//直接构造alloc.construct(sp+1,string(b,e));//使用复制构造函数

eg://Vector.h#ifndef __VECTOR_ALLOC_H__#define __VECTOR_ALLOC_H__/* * *function:A very simple vector template class and incompletely and many bugs but I have no time to fix them *author:vv_VV_vv *time:2012-12-20 14:06:36 */#include <memory>#include <cstddef>#include <limits>#include <exception>template <class T>class Vector{public:typedef T* iterator;Vector():elements(0),first_free(0),m_end(0){}void push_back(const T &t);void pop_back();T& operator[](std::size_t N){return elements[N];}const T& operator[](std::size_t N) const{return elements[N];}std::size_t size() const{return first_free-elements;}std::size_t capacity() const{return m_end-elements;}void reserve(std::size_t N){if (std::numeric_limits<std::size_t>::max()<N){throw std::out_of_range("reserve too long!");}else if (capacity()<N)//重新分配{//记录vector.size()std::ptrdiff_t size=first_free-elements;//给出新vector.capacity()大小,大小为原来vector.size()的两倍std::ptrdiff_t newCapacity=N;//分配新内存,大小为newCapacity()T *newElements=alloc.allocate(newCapacity);//复制原数据,把elements到first_free,复制到newElements指针处std::uninitialized_copy(elements,first_free,newElements);//析构原数据,从后到前依次析构for (T *p=first_free; p != elements;){alloc.destroy(--p);}//释放原数据,头指针为elements,大小为从m_end-elementsif (elements){alloc.deallocate(elements,m_end-elements);}//重新赋值elements first_free m_endelements=newElements;first_free=elements+size;m_end=elements+newCapacity;}}void resize(size_t N){if (N<size()){for (T *p=elements; p != elements+N; ++p){alloc.destroy(p);}first_free=elements+N;}else if (size()<N){reserve(N-size());std::uninitialized_fill_n(m_end,N-size(),T(0));m_end+=N+size();}}void clear(){if (!empty()){for (T *p=first_free; p != elements;){alloc.destroy(--p);}if (elements){alloc.deallocate(elements,m_end-elements);}elements=first_free=m_end=0;}}bool empty() const{return elements==first_free;}iterator begin() const{return elements;}iterator end() const{return first_free;}friend bool operator==(const Vector<T> &lhs,const Vector<T> &rhs);friend bool operator!=(const Vector<T> &lhs,const Vector<T> &rhs);//operator* and const versionT& operator*(){return *first_free;}const T& operator*() const{return *first_free;}T& operator++()//prefix ++{if (first_free==m_end){throw std::out_of_range("++m_end() is forbidden!");}++first_free;return *this;}T& operator++(int)//postfix ++{T ret(*this);++*this;return ret;}T& operator--()//prefix --{if (elements<first_free){throw std::out_of_range("--beg() is forbidden!");}--first_free;return *this;}T& operator--(int)//postfix --{T ret(*this);--*this;return ret;}private://declarestatic std::allocator<T> alloc;void reallocate();T *elements;//first oneT *first_free;//last of the m_endT *m_end;//capacity m_end/*0              5  6         |--1--2--3--4--|--|------------|    elemnts      first_free   m_end*/};//definetemplate <class T> std::allocator<T> Vector<T>::alloc;template <class T>void Vector<T>::push_back(const T &t){if (first_free==m_end){reallocate();}alloc.construct(first_free,t);//same as placement new : new (first_free) T(t);++first_free;}template <class T>void Vector<T>::pop_back(){if (empty()){throw std::logic_error("vector is empty!");}alloc.destroy(first_free);--first_free;}//整体思路/*1.新数据大小,newCapacity=2*std::max(size,1)2.分配新数据内存,alloc.allocate(newCapacity)3.复制原数据,std::uninitialized_copy(原数据elements,原数据first_free,新数据newElements)4.析构原数据,alloc.destroy(pointer)5.释放原数据,alloc.deallocate()6.重新整理指针*/template <class T>void Vector<T>::reallocate(){//记录vector.size()std::ptrdiff_t size=first_free-elements;//给出新vector.capacity()大小,大小为原来vector.size()的两倍std::ptrdiff_t newCapacity=2*std::max(size,1);//分配新内存,大小为newCapacity()T *newElements=alloc.allocate(newCapacity);//same as : T *newElements=static_cast<T*>(operator new[](newCapacity*sizeof(T));//复制原数据,把elements到first_free,复制到newElements指针处std::uninitialized_copy(elements,first_free,newElements);//析构原数据,从后到前依次析构for (T *p=first_free; p != elements;){alloc.destroy(--p);}//释放原数据,头指针为elements,大小为从m_end-elementsif (elements){alloc.deallocate(elements,m_end-elements);//same as : operator delete[] (elements);}//重新赋值elements first_free m_endelements=newElements;first_free=elements+size;m_end=elements+newCapacity;}template <class T>bool operator!=(const Vector<T> &lhs,const Vector<T> &rhs){if (lhs.first_free!=rhs.first_free){return true;}return false;}template <class T>bool operator==(const Vector<T> &lhs,const Vector<T> &rhs){return !(lhs!=rhs);}#endif//__VECTOR_ALLOC_H__
//main.cpp#include "Vector.h"#include <iostream>using std::cin;using std::cout;using std::endl;int main(){Vector<int> vec;vec.push_back(1);vec.push_back(2);vec.push_back(3);for (int i = 0; i != vec.size(); ++i){cout<<vec[i]<<'\t';}cout<<endl;for (Vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++iter){cout<<*iter<<'\t';}vec.pop_back();cout<<endl;for (Vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++iter){cout<<*iter<<'\t';}vec.reserve(1);cout<<endl;for (Vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++iter){cout<<*iter<<'\t';}vec.resize(1);cout<<endl;for (Vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++iter){cout<<*iter<<'\t';}char ch;cin>>ch;return 0;}

原创粉丝点击