第18章 特殊工具与技术(2)
上一篇:http://www.zzzyk.com/kf/201201/116032.html18.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++ ,