6.1 对象的构造解构
destructor会被放在对象被构造出来以后的每一个离开点(当object还存活),如每一个return。所以尽量将object放在使用它的那个区段附近。可以节省不必要的对象产生操作和摧毁操作。
全局对象
Matrix identity;
int main()
{
Matrix m1=identity;
return 0;
}
identity在被第一次调用之前构造出来,在main函数结束之前被摧毁。并且都是静态的初始化操作和内存释放操作。
munch策略
1.为每一个需要静态初始化的档案产生一个_sit函数(sit就是static initialization的缩写),内带必要的constructor调用操作或inline expansion。
_sit_matrix_c_identity()
{
identity.Matrix::Matrix();
}
2.类似情况,在一个需要静态内存释放操作的文件中,产生一个_std()函数(std就是 static deallocation),内带必要的destructor调用操作,或是其inline expansion
3.提供一组runtime library "munch"函数:一个_main函数(用以调用可执行文件中的所有_sit函数),以及一个exit()函数(以类似的方式调用所有的_std()函数)
局部静态对象
const Matrix& identity(){
static Matrix mat_identity;
return mat_identity;
}
1.mat_identity的constructor必须只能被施行一次,虽然上述identity()函数可能被调用很多次
2.mat_identity的destructor必须只能被施行一次,虽然上述identity()函数可能被调用很多次
对象数组
Point knots[10];
如果Point既没有定义一个constructor也没有定义一个destructor,那么上述操作也就和内置类型所组成的数组的操作差不多,就是配置足够的内存存储10个连续的Point元素
如果Point定义了default destructor,destructor必须轮流施行于每一个元素之上,通过vec_new()函数
void* vec_new(
void *array,//数组起始地址,如果不是具名数组则为0,如果是0,则是new,配置于heap
size_t elem_size, //每一个class object的大小
int elem_count, //数组中元素数目
void(*constructor)(void*), //元素对应的constructor和destructor的指针
void(*destructor)(void*,char)
)
如果有明显的初始值给class objects组成的数组,vec_new不在必要,vec_new只对没有提供明显初始值的部分进行初始化
vec_new(&knots,sizeof(Point),10,&Point::Point,0);
在knots生命结束时,经由vec_delete()函数,销毁元素
void* vec_delete(
void *array,//数组起始地址,如果不是具名数组则为0,如果是0,则是new,配置于heap
size_t elem_size, //每一个class object的大小
int elem_count, //数组中元素数目
void(*destructor)(void*,char)
)
default constructor和数组
在创建对象数组时,如果提供的constructor带有默认的参数,编译器会在内部产生一个stub constructor
class Point{
public:
Point(float x=0.0,float y=0.0);
}
//stub constructor
Point::point()
{
Point(0.0,0.0);
}
6.2new和delete运算符
int* pi=new int(5);
1.通过适当的new运算符函数实体,配置所需的内存
//调用函数库中的new运算符
int* pi=_new(sizeof(int))
2.给配置得来的对象设立初值(在内存配置成功后)
*pi=5
delete pi;
情况类似
if(pi!=0)
_delete (pi);
注意,delete之后只是pi所指对象之生命结束了,此时pi所指地址上的对象不在合法,但地址本身仍然合法
针对数组的new语意
如果对象数组所对应的class没有constructor和destructor,则vec_new 不会被调用,但如果存在,vec_new就会被调用
Pint3d *p_arry;
p_arry=vec_new(0,sizeof(Point3d),10,&Point3d::Point,&Point3d::~Point3d);
因为动态分配,不具名数组,所以第一个参数是0。
尽量不要用一个base指针指向Derived数组,因为如果destructor不是virtual,delete就只会调用base class的destructor,而Derived部分并没有被销毁