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

内存管理元素

2013年08月11日 ⁄ 综合 ⁄ 共 4014字 ⁄ 字号 评论关闭

1、三个最重要算法:uninitialized_copy、uninitialized_fill、uninitialized_fill_n 会构造新的对象object,而copy、fill、fill_n会赋新值于已存在的对象上。

 

2、construct 构造器:

template <class T1,class T2>

void construct(T1* p,const T2& value);

construct(p,value) <=> new(p) T1(value) 

【注意】p所指的内存未经初始化,没有任何object构造于p所指位置。 内存大小:sizeof(T1)

HP实现品,construct声明于头文件<algo.h>,SGI实现品,则声明于头文件<memory>;而C++标准并不涵盖construct

【举例】

string* strsp = (string*)malloc(sizeof(string));  //strsp指向未经初始化的一块内存区域

construct(strsp,"test"); //构造器初始化值test

assert(strcmp(strsp->c_str(),"test")==0);     //判定strsp指针指向的内存区域的字符是否是test

 

3、destory 析构销毁:

C++中,利用delete来先调用某个对象的destructor,然后释放该对象所占内存。利用destory来先调用某个对象的destructor(destructor T::~T()),而不释放该对象所占内存。(2)则是析构Range[first,last)中所有的对象,相当于在针对[first,last)中的每个iterator i调用destory(&*i)。

(1)template <class T> void destory(T* pointer);

(2)template <class ForwardIterator> void destory(ForwardIterator first,ForwardIterator last);

【举例】

class Int{

 public:

  Int(int x):val(x){}

  int get(){return val;}

 private:

  int val;

};

int main(){

  int A[]={Int(1),Int(2),Int(3)}; //初始化数组A,定义三个Int型的对象

  destory(A,A+3);  //析构从指向A的第1个对象到指向A的第3个对象即Int(1),Int(2),Int(3),并不释放内存

  construct(A+0,Int[11]); //重新在原有内存构造Int[11]的对象

  construct(A+1,Int[12]); //重新在原有内存构造Int[12]的对象

  construct(A+2,Int[13]); //重新在原有内存构造Int[13]的对象

}

 

4、uninitialized_copy:(复制)

template<class InputInterator,class ForwardInterator>

ForwardInterator uninitialized_copy(InputInterator first,InputInterator last,ForwardInterator result);

针对输入区间Range[first,last)中的每一个intertor i,uninitialized_copy会调用construct(& *(result+(i-first)),*i),并产生*i 的复制品,放于输出区间的相对位置。

【注意】C++标准要求uninitialized_copy具有构造所有必要的元素,或者一旦有其中一个copy construct失败时,不构造任何东西。

【举例】

class Int{

public:

 Int(int x):val(x){}

 int get(){return val;}

private:

 int val;

};

int main(){

 int A1[]={1,2,3,4,5,6,7};

 const int N = sizeof(A1)/sizeof(Int);   //确定每个Int区域所占多少内存大小

 Int* A2=(Int*)malloc(N * sizeof(Int)); //为A2分配一块同A1相同内存大小的内存区域

 uninitialized_copy(A1,A1+N,A2); //从A1复制元素到A2

}

 

5、uninitialized_fill: (填充)

  template<class ForwardInterator,class T>

  void uninitialized_fill(ForwardInterator first,ForwardInterator last,const T& x);

Range[first,last)中产生x的复制品,使得内存分配与对象构造行为分离。相当于在range中的每个interator i ,uninitialized_fill会调用constructor(&*i,x),并在该位置产生x的复制品。

【区别】希望实现一个constructor,能够以某个特定区域构造容器,则使用uninitialized_copy;希望实现一个constructor,能够将容器中的每个元素初始化为x值,则使用uninitialized_fill.它要不就产生所有必要的元素,要不就不产生任何元素。如果有任何一个copy constructor抛出异常,则uninitialized_fill必须能够将已产生的所有元素析构掉。

【举例】

class Int{

public:

Int(int x):val(x){}

int get(){return val;}

private:

int val;

};

int main(){

const int N=137;

Int val(46);

Int* A=(Int*)malloc(N * sizeof(Int)); //为A2分配一块同A1相同内存大小的内存区域

uninitialized_fill(A,A+N,val); //将A中的每个元素复制成val值。

}

 

6、uninitialized_fill_n:

template <class ForwardInterator,class Size,class T>

ForwardInterator uninitialized_fill_n(ForwardInterator first,Size n,const T& x);

与uninitialized_fill不同的是,uninitialized_fill_n操作于一个interator加上一个元素个数所表现得rang上,即Range[first,first+n),它可以与OutputInterator搭配。相当于在range[first,first+n)中的每个interator i ,uninitialized_fill_n会调用constructor(&*i,x),并在该位置产生x的复制品。

当然,它要不就产生所有必要的元素,要不就不产生任何元素。

【举例】

class Int{

public:

Int(int x):val(x){}

int get(){return val;}

private:

int val;

};

int main(){

const int N=137;

Int val(46);

Int* A=(Int*)malloc(N * sizeof(Int)); //为A2分配一块同A1相同内存大小的内存区域

uninitialized_fill(A,N,val); //将A中的每个元素复制成val值。

}

 

7、临时缓冲区(Temporary Buffers)

算法:stable_sort和inplace_merge 是adaptive的。他们会尝试分配额外的临时空间来放置中介结果。

get_temporary_buffer() 分配未初始化临时性的内存

 template<class T> pair<T*,ptrdiff_t>get_temporary_buffer(ptrdiff_t len);

return_temporary_buffer() 归还该内存块

 template<class T> void return_temporary_buffer(T* p);

如果一个函数以get_temporary_buffer() 分配内存,则函数返回前必须以return_temporary_buffer() 来归还内存。必须以uninitialfied_fill来做初始化,同理,必须在利用return_temporary_buffer() 归还内存之前,先将缓冲区中的所有对象析构掉。

【结论】constructor应该以get_temporary_buffer分配缓冲区,并在其内uninitialfied_fill进行初始化,而destructor必须析构所有元素并归还该缓冲区。

 

【举例】

int main(){

 pair<T*,ptrdiff_t> P = get_temporary_buffer<int>(1000); //分配1000个元素的缓冲区大小

 int* buf =P.first; //指向缓冲区第一个存储单元

 ptrdiff_t N =P.second; //指定缓冲区第二个存储单元与第一个间的距离N

 uninitialized_fill_n(buf,N,42); //为缓冲区内存区域初始化42

 int* result  = find_if(buf,buf+N,bind2nd(not_equal_to<int>(),42)); //指定缓冲区中不等于42的值

 assert(result==buf+N); //结束就停止

 return_temporary_buffer(buf); //析构所有元素并归还该缓冲区。

}

抱歉!评论已关闭.