《深度探索C++对象模型》读书笔记:第6章 执行期语意学

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部分并没有被销毁

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值