- 作者: 雪山肥鱼
- 时间:20210914 22:47
- 目的: 临时对象,全局对象,局部静态对象
临时对象
void fun()
{
{
//调用析构
A obja;
}
int b = 0;
b = 10;
}
临时对象出了作用域就会调析构。
所以插入临时对象的时机,会影响开销
/*
A obja 放在 if之后 比放在 if 之前会高效一些。
int i ;
int j ;
...
if(1)
{
return
}
A obja;
obja.m_i = 10;
*/
这种插在if之前会比差在之后多一点开销。插在前面,无论如何都会多一次构造和析构。
return 与 临时对象的析构
void fun1()
{
A obja;
int mytest = 1;
if (mytest == 0)
{
return;
}
int b = 0;
b = 10;
return;
}
两个return的地方都会准备了析构函数。起始还是那句话,只要除了作用域,编译器就会在此处插入析构
全局对象
namespace sp2
{
class A
{
public:
A()
{
cout << "A::A()" << endl;
}
~A()
{
cout << "A::~A()" << endl;
}
int m_i;
};
A g_aobj;
}
全局对象在数据段,如果未被初始化,则全局对象内存全部清0 包括其内部的m_i = 0.
全局变量的构造函数发生在main函数之前,不管有没有调用到,都会把空间分配出来。不像临时变量,调到你才会被分配。
如果不重新生成项目,则全局变量的地址永远不会发生改变。
局部静态对象的构造
测试代码
namespace sp1
{
class A
{
public:
A()
{
cout << "A::A()" << endl;
}
~A()
{
cout << "A::A()" << endl;
}
int m_i;
};
void myfun()
{
static A m_obj1;
static A m_obj2;
printf("m_obj1 address:%p\n", &m_obj1);
printf("m_obj2 address:%p\n", &m_obj2);
}
/*
void func()
{
}
*/
void func()
{
//只构造一次
myfun();
myfun();
}
}
放开空函数 func() 进行测试得到结论:
- 与全局static不同,不主动调用局部静态变量,则不会对其进行构造
- 如果调用,则在编译期间就确定了变量地址
- 如果未初始化,则局部静态对象的内存内容全部被初始化为0
- 局部静态对象只会构造一次。
为什么只会构造一次
对于静态对象,在其构造的时候,对其内存增加标识。以vs2017 为例。
汇编查看static.PNG
代码走到static A obj 后,会走到一行 initial thread_header 的标记,跳到08D1109h 后,查看均为0 .
汇编查看2.PNG随后代码走完 init_thread_footer 后08D11CCh 后跟的4个字节 置换成了01000080h。
这就是标记,如果编译器下次再走过来,发现这里有此标记,则不会再进行构造了。所以局部静态对象只会被构造一次。
局部静态变量的析构
放在了 main 函数执行之后的 _aexit();
相当于做个钩子。
aexit析构.PNG aexit析构2.PNG
局部静态对象数组
const A & myfunc()
{
static A obj[5];
}
数组内存应该是 连续的 已经分配了, 无论是编译的适合就分配好在bss段,还是 后续分配的空间,无所谓了,记得在bss里分配即可.
但是太大也不会分配。感觉类似 demangding page.
网友评论