当前位置:编程学习 > C/C++ >>

第18章 特殊工具与技术(2)

上一篇:http://www.zzzyk.com/kf/201201/116032.html

18.1.3 operator new函数和operator delete函数

当使用new表达式的时候,实际上发生了三个步骤。首先该表达式调用名为operator new的标准库函数,分配足够大的原始的未类型化的内存,以保存指定类型的一个对象;接下来,运行该类型的一个构造函数,用指定初始化式构造对象;最后,返回指向新分配并构造的对象的指针。

当使用delete表达式delete sp;删除动态分配对象的时候,发生两个步骤。首先,对sp指向的对象运行适当的析构函数;然后,通过调用名为operator delete的标准库函数释放该对象所用内存。

标准库函数operator new和operator delete的命名容易让人误解。与其他opertaor函数(如operator=)不同,这些函数没有重载new或delete表达式,实际上,我们不能重定义new和delete表达式的行为。

通过调用operator new函数执行new表达式获得内存,并接着在该内存中构造一个对象,通过撤销一个执行delete表达式,并接着调用operator delete函数,以释放该对象使用的内存。

因为new(或delete)表达式与标准库函数同名,所以二者容易混淆。

1. operator new和operator delete接口

operator new和operator delete函数有两个重载版本,每个版本支持相关的new表达式和delete表达式。


void *operator new(size_t); //allocate an object  
void *operator new[](size_t); //allocate an array  
 
void operator delete(void*); //delete memory of an object  
void operator delete[](void*); //delete memory of an array 
void *operator new(size_t); //allocate an object
void *operator new[](size_t); //allocate an array

void operator delete(void*); //delete memory of an object
void operator delete[](void*); //delete memory of an array

2. 使用分配操作符函数

虽然operator new和operator delete函数的设计意图是供new表达式使用,但它们通常是标准库中的可用函数。可以使用它们获得未构造内存,它们有点类似allocator类的allocate和deallocate成员。


template<class T> 
class Vector{ 
public: 
    Vector():elements(0),first_free(0),end(0){} 
    void push_back(const T&); 
    void *operator new[](size_t); //allocate an array  
    void operator delete[](void*); //delete memory of an array  
private: 
    static std::allocator<T> alloc; 
    void reallocate(); 
    T* elements; //first element  
    T* first_free; //behind the last actual element  
    T* end; //behind vector conent  
}; 
 
template<class T> 
void Vector<T>::push_back(const T& t){ 
if(first_free==end) 
    reallocate(); //gets more space and copies existing elements to it  
alloc.construct(first_free,t); 
++first_free; 

 
template <class T> 
void Vector<T>::reallocate(){ 
std::ptrdiff_t size=first_free-elements; 
std::ptrdiff_t newcapacity=2*max(size,1); 
T* newelements=static_cast<T*>(alloc.operator new[](newcapacity)); 
 
uninitialized_copy(elements,first_free,newelements); 
 
for(T *p=first_free;p!=elements;){ 
alloc.destroy(--p); 

 
if(elements) 
    alloc.operator delete[](elements,end-elements); 
 
elements=newelements; 
first_free=elements+size; 
end=elements=newcapacity; 

template<class T>
class Vector{
public:
 Vector():elements(0),first_free(0),end(0){}
 void push_back(const T&);
 void *operator new[](size_t); //allocate an array
 void operator delete[](void*); //delete memory of an array
private:
 static std::allocator<T> alloc;
 void reallocate();
 T* elements; //first element
 T* first_free; //behind the last actual element
 T* end; //behind vector conent
};

template<class T>
void Vector<T>::push_back(const T& t){
if(first_free==end)
 reallocate(); //gets more space and copies existing elements to it
alloc.construct(first_free,t);
++first_free;
}

template <class T>
void Vector<T>::reallocate(){
std::ptrdiff_t size=first_free-elements;
std::ptrdiff_t newcapacity=2*max(size,1);
T* newelements=static_cast<T*>(alloc.operator new[](newcapacity));

uninitialized_copy(elements,first_free,newelements);

for(T *p=first_free;p!=elements;){
alloc.destroy(--p);
}

if(elements)
 alloc.operator delete[](elements,end-elements);

elements=newelements;
first_free=elements+size;
end=elements=newcapacity;
}这些函数的表现与allocator类的allocate和deallocate成员类似。但是,它们在一个重要方面有不同:它们在void*指针而不是类型化的指针上进行操作。

一般而言,使用allocator比直接使用operator new和operator delete函数更为类型安全。

allocate成员分配类型化的内存,所以使用它的程序可以不必计算以字节为单位的所需内存量,它们也可以避免对operator new的返回值进行强制类型转换。类似地,deallocate释放特定类型的内存,也不必转换为void*。

摘自 xufei96的专栏
 

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,