为自定义类型的数组分配空间得小心,陷阱很多。
首先,如下code是有问题的。
T* at = new T[1];
delete aT; //Error! using delete []
保持new[]和delete[]正确的成对使用很重要,因为数组的分配和归还所使用的函数不同于非数组;数组用operator new[]和operator delete[],而非数组使用operator new和operator delete来分配内存。
其次,从逻辑上说,只要声明了非数组形式的函数(op new和op delete),就应该为这些函数声明数组的形式。然而奇怪的是,在日常编程实践中,这一点往往被人所忽视。
如果是想调用全局的数组分配操作,那么,“仅仅转发对全局形式的调用”,可以让事情变得清晰。
class T{
public:
void* operator new (std::size_t size) ;
void* operator delete (void *) ;
void* operator new[] (std::size_t size) {return ::operator new ( size) ;}
void* operator delete[] (void *p) {return ::operator delete(p) ;}
};
如果不鼓励分配T数组,那么可以直截了当地把函数声明为private并且不提供定义。
另一个容易产生错误的地方在于,传递给op new[]的那个表示大小的参数值,取决于函数是如何被调用的。
如果直接调用op new或者op new[]时,这个大小正是分配的对象的大小。
aT = new T;
aT = static_cast<T*>(operator new (sizeof(T) ));
arrayT = static_cast<T*>(operator new[] (5*sizeof(T) ));
但是,隐式的调用op new[]时,编译器会略微增加一些内存请求。
arrayT = new T[5]; //请求内存量为 5*sizeof(T) + delta个byte
这里所请求的额外空间用来记录关于数组的一些信息(个数,单个元素的大小等),对以后回收内存是必不可少的。
不过,事情远远没有那么简单,这个额外空间对于不同数组分配而言,其大小也是会变化的。
如果你真的需要考虑这种情况,那么你必须避免编译器的干预,取而代之的是,使用普通的operate new