对象的构造和析构
讲解在
以下几种情况下
编译器是如何安插构造和析构函数?
1.全局对象
2.局部静态对象
3.数组对象
1)全局对象
Matrix g_identity;
main() {
Matrix m = g_identity ;
}
c++保证了在main函数中第一次用到g_str之前,将g_str构造出来,在main()函数结束之前将g_str毁掉。
一个global class只能够被一个常量表达式(编译期间求其值得那种)。非class全局变量在编译期间可以放置在data segment并且指定特定的值(如int g_tmp),但是如果是class全局变量,可以放置在data segment并且制定为0,但是构造函数一定要到程序运行时才会实施。
针对class全局变量采用munch策略:
1. 为每一个需要静态初始化的文件产生一个_sti函数。如之前的g_identity,会在matrix中产生_sti函数(static initialization)
_sti_matrix_c_identity() {
g_identity.Matrix::Matrix();
}
2.类似会产生一个_std函数,针对每个静态初始化对象条用destructor
3.提供一组runtime library“munch”函数:一个_main()函数(用以调用可执行文件中的所有_sti()函数),以及一个exit()函数(所有_std()函数)
int main() {
_main(); //调用所有的_sti_xxx
...
_exit(); //调用所有的_std_xxx
}
如何收集各个object file中的_sti()函数和std()函数呢?
nm命令(
列出一个目标文件中的各种符号),将符号表的信息导入到munch程序,然后通过munch根据符号表的名称,搜寻_sti和_std开头的名称,将这些函数名称加入到一个jump table中,接下来将这个表格写入到program text文件中,然后cc命令重新期货,将这个内含jump table的文件加以编译,整个可执行文件然后被重新链接。
2)局部静态对象
const Matrix& identity() {
static Matrix m;...
}
局部静态对象必须只能够构造和析构一次,采用方法导入一个临时性对象用以保护m的初始化操作,第一处理identity函数,这个临时对象为false,调用过之后设置回true,destructor类似。
3)数组对象
Point knots[10];
需要配置内存来存10个连续的Poingt元素,同时调用default构造函数,轮流施于每个元素之上。
void* vec_new {
void* array, // 数组起始地址size_t elem_size, //每个object的大小int elem_count, //元素个数void (*constructor)(void*),void (*destructor)(void*, char)
}
针对编译器很可能转换为
vec_new(&knots, sizeof(Point), 10, &Point::Point, 0);
释放的时候也会有类似的vec_delete.
void* vec_delete {
void* array, // 数组起始地址
size_t elem_size, //每个object的大小
int elem_count, //元素个数
void (*destructor)(void*, char)
}