对象的生命期

无名对象的生命期


class X{
public:
	void *ptr;
	X(){ ptr=(void*)1;RepStatF("Construct X"); }
	~X(){ ptr=0;RepStatF("Destruct X"); }
};
void f(void *ptr){ RepStatF("In f: %lu",ptr); }
int main(int argc,char *argv[]){
	f(X().ptr);
	/**
	 * 查看汇编文件:
	 *     call	_ZN1XC1Ev //构造一个X对象
	 *     call	_Z1fPv
	 *     call	_ZN1XD1Ev //释放X对象
	 * 因此此时就至关于:
	 *  	X _noname;
	 *  	f(_noname.ptr);
	 *  	_noname.~X()
	 **/
	return 0;
}


全局变量/静态变量


  • 生命期从程序开始到程序结束,也即在整个程序执行期间都存在.多线程

  • 底层实现:g++是把全局变量/静态变量(包括在{}内定义的静态变量)放在程序文件的数据段,内核执行程序文件的惟一方法就是经过exec()加载.而exec()会从程序文件中加载数据段与正文段,也即全局变量/静态变量在程序开始执行以前就已经存在了.函数

void f(){ static int fffifff=33; }/* 函数内的静态变量 */
int iii=77;	/* 全局变量 */
---------------------------------------------------
.data		/* 数据段 */
	.align 4
	.type	iii, @object
	.size	iii, 4
iii:			/* 全局变量 */
		.long	77
	.align 4
	.type	_ZZ1fvE7fffifff, @object
	.size	_ZZ1fvE7fffifff, 4
_ZZ1fvE7fffifff:	/* 静态变量,进行了名称修改 */
		.long	33


全局类对象


  • 定义在全局做用域的对象是放在程序的bss段,模式:
    .bss
    全局对象名 .zero 全局对象所占字节(即sizeof(全局对象))this

  • _Z41__static_initialization_and_destruction_0ii这个函数中完成对全局类对象构造函数的调用,以及析够函数的注册.spa

    • 由于只有exit()函数会依次调用清理处理程序,因此只有当直接调用exit()退出时或者从main函数返回(此时返回到特殊启动例程,该例程会调用exit())才会调用全局类对象的析够函数.线程

    • 将析够函数经过__cxa_atexit()注册为程序清理处理程序,即在进程退出前调用.翻译

    class X{
    	char _buf[16];
    public:
    	X(const char *buf){ strcpy(_buf,buf);Println("构造: %s",_buf); }
    	~X(){ Println("析够: %s",_buf); }
    };
    X x1("HelloWorld");
    int main(int argc,char *argv[]){
    	_exit(0);	/* 此时不会调用x1的析够函数,不过也不须要,由于进程已经终止了 */
    	exit(0);	/* 或者 return 0,此时会调用析钩函数 */
    }
    ----------------------------------------
    	.globl	x1
    	.bss		/* bss段进行变量的定义 */
    	.align 16
    	.type	x1, @object
    	.size	x1, 16
    x1: 	.zero	16	/* 16个字节 */
    _Z41__static_initialization_and_destruction_0ii:/* 构造函数调用与析够函数注册 */
    	movl	$.LC2, %esi 	/* buf参数 */
    	movl	$x1, %edi   	/* this指针 */
    	call	_ZN1XC1EPKc	/* 调用构造函数 */
    	movl	$__dso_handle, %edx
    	movl	$x1, %esi   	/* this指针 */
    	movl	$_ZN1XD1Ev, %edi/* 析够函数地址 */
    	call	__cxa_atexit    /* 注册析钩函数 */


    局部类对象


    • 存放在程序文件的bss段,模式:.comm 修饰后的对象名 对象占用字节指针

    • 构造函数是在函数(更具体:在对象所处的做用域)中调用,析钩函数也是在函数中进行注册,而且只会调用/注册一次.如code


    if(函数第一次执行){/* 确保了在多线程中静态对象也只会被初始化一次. */
    	调用构造函数
    	注册析钩函数
    }

    class X{
    public:
    	X() 	{ RepStatF("构造函数"); }
    	~X()	{ RepStatF("析钩函数"); }
    };
    
    void* test(void *){
    	static X x;	/* 只会被初始化一次 */
    	RepStatF("Creating...");
    	RepStatF("Exiting...");
    	return 0;
    }
    
    int main(int argc,char ** argv){
    	RepStatF("main Thread...");
    	CT.create(test);/* 线程1 */
    	CT.create(test);
    	/* 此时'线程1'在执行test()函数中已经完成了对静态局部变量x
    	 * 的初始化,因此该线程不会初始化x. */
    	CT.sleepus(3000000);
    }
    /* -----------------运行输出---------------------------------------------- */
    PID		线程ID				时间			说明
    4628: 0x7f921f88d740: 1394381143949726: main Thread...
    4628: 0x7f921e882700: 1394381143966725: 构造函数/* 在最初建立的线程中进行初始化 */
    4628: 0x7f921e882700: 1394381143966771: Creating...
    4628: 0x7f921e882700: 1394381143966788: Exiting...
    4628: 0x7f921e081700: 1394381143966779: Creating...
    4628: 0x7f921e081700: 1394381143966867: Exiting...
    4628: 0x7f921f88d740: 1394381146959016: 析钩函数/* 在主线程进行初始化 */



    注意


    • 由上知,在函数内部定义静态变量,变量只会被初始化一次,因此如下会有意料的结果:对象

    void f(int i){
    	static int x=i>7?3:7;
    	Println("HelloWorld: %d",x);
    	/**
    	 * f()翻译成汇编应该是:
    	 * if(函数第一次执行){
    	 * 	if(i>7) mov 3,x;
    	 * 	else mov 7,x;
    	 * }
    	 * mov "HelloWorld",%rdi
    	 * call printf
    	 **/
    }
    int main(int argc,char *argv[]){
    	f(9);	/* 输出'HelloWorld: 3' */
    	f(2);	/* 输出'HelloWorld: 3' */
    }
    	-------------------------------------------------------------
    class X{
    	char _buf[16];
    public:
    	X(const char *buf){ strcpy(_buf,buf);Println("构造: %s",_buf); }
    	~X(){ Println("析够: %s",_buf); }
    };
    void f(const char *buf){
    	static X x1(buf);
    }
    int main(int argc,char *argv[]){
    	f("Hello");	/* 输出Hello */
    	f("World");	/* 输出Hello */
    }
    相关文章
    相关标签/搜索