国庆假期小栖,继续整理第六章的内容。
关于new和delete运算符。
a. 使用new运算符构造对象时, 例如:
Point3d* origin = new Point3d;
会被转化为两个操作:分配空间和调用类的构造函数:
Point3d* origin;
if(origin = __new(sizeof(Point3d)))
{
origin = Point3d::Point3d(origin);
}
同样的,使用delete释放对象时,例如:
delete origin;
会被转化为两步操作:调用类的析构函数和释放内存:
if(0 != origin)
{
Point3d::~Point3d(origin);
__delete(origin);
}
b. 对于数组的new语义,会有vec_new调用产生一整组对象,例如:
Point3d* p_array = new Point3d[10];
通常会被编译为:
Point3d* p_array;
p_array = vec_new(0, sizeof(Point3d), 10, &Point3d::Point3d, &Point3d::~Point3d);
注意针对new p_array[N]产生的对象数组释放时必须调用delete [] p_array. c. Placement operator new语义
Placement new是一个预先定义好的重载的new运算符,其作用是在已经申请好的内存上直接构造对象,例如:
Point2w* ptw = new(arena) Point2w;//arena为已申请内存的地址
arena指向一块内存区,用以放置产生的Pointw对象。他需要两个参数,其实现很简单,将获得的指针(上例中的arena)所指的地址传回:
void* operator new(size_t, void* p)
{
return p;
}
类似于:
Point2w* ptw = (Point2w*) arena;
但这只是该操作符扩充的一半,另一半是将Point2w的构造函数实施与arena所指的地址上:
if(0 != ptw)
{
ptw->Point2w::Point2w();
}
注意,如果placement new在原已存在一个object的内存上构造新的object:
Point2w* ptw = new(arena) Point2w;
//...do something
ptw = new(arena) Point2w;
而现有object有一个析构函数,那么改析构函数不会被调用,我们知道,调用delete object会调用该object的析构函数,但是此处不可以这样做,因为,delete不但会调用析构函数,而且会释放内存,那样arena就不能继续使用了,所以我们需要做的是仅仅调用object的析构函数:
ptw->~Point2w();
注:标准C++提供了placement operator delete,它会调用析构函数而不释放内存。
之后会继续整理第六章剩下的内容,关于临时对象的。