對象的生命期

無名對象的生命期


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 */
    }
    相關文章
    相關標籤/搜索