C++中引用和匿名對象的理解和本質剖析

        你們對C++的引用應該都不陌生吧,抱着既要知其然,也要知其因此然的態度。java

        下面將按照是什麼?怎麼用?爲何須要?本質剖析的流程來想你們一一描述。程序員

引用時什麼?函數

        引用其實就是給變量起的一個別名,使用這個別名跟使用變量名沒有區別。spa

        那什麼又是變量名呢?指針

        變量名實質上是一段連續存儲空間的別名,是一個標號(門牌號),編譯器經過變量來申請並命名內存空間,程序員能夠經過變量的名字可使用存儲空間。code

        也能夠這樣理解,變量名是邏輯概念,變量是物理層面,變量含數據類型和數據值,數據類型決定內存的分配,編譯器將變量名和變量對應的內存聯繫起來,使程序員能夠經過變量名來操做內存。對象

引用怎麼用?生命週期

      語法:Type& name = var;內存

      規則:一、普通引用在聲明時必須用其它的變量進行初始化編譯器

                二、引用做爲函數參數聲明時不進行初始化(後面將經過引用本質來解釋緣由)

爲何須要引用?

        1)引用做爲其它變量的別名而存在,所以在一些場合能夠代替指針

        2)引用相對於指針來講具備更好的可讀性和實用性

        引用爲java等高級的語言程序員提供了很大便利,其不須要了解C++中的指針,只須要按照之前的習慣來使用就能夠。

引用的本質剖析(很重要!!)

        一、引用實際上是個常量,證實以下  

int main()
{
	int a = 1;
	//int& b;   C++編譯器提示:錯誤「b」,必須初始化引用-->說明引用是個常量
	int& b = a;
}

       說明: 必須初始化引用-->說明引用是個常量       

        二、引用其實也是個指針,證實以下            

struct teacher
{
	int age;		//4個字節
	teacher& m_techer;	
};

struct student
{
	int age;               //4個字節
	short& weight;
};

int main()
{
	cout<<"sizeof(teacher):"<<sizeof(teacher)<<endl; /*輸出sizeof(teacher):8-->說明m_techer的
	                                                    引用佔4個字節*/
	cout<<"sizeof(student):"<<sizeof(student)<<endl; /*輸出sizeof(student):8-->說明weight的引
	                                                    用佔4個字節*/
	system("pause");
	return 0;
}

        說明:從上面teacher&和short&的兩個引用中佔用的4個字節(32位系統),能夠推斷出引用實際上是個指針。

        根據一、2的結論能夠推斷出引用實際上是個指針常量或者是常量指針,下面進一步證實。

        三、引用實際上是個指針常量 ,證實以下

int main()
{
	int a =10;
	int m = 22;

	int& b = a;
	&b = &m;      /*疑問:  b是引用,引用是個指針,指針賦值爲何還要在取地址符&b
	                    (由於編譯器在咱們使用引用時,自動給引用披上了間接引用的外衣即:*b)
       		        編譯錯誤 「=」: 左操做數必須爲左值-->引用是個指針常量,不能修改
       		          其指針的指向。*/
	
	system("pause");
	return 0;
}

        說明:引用是個指針常量。下面會說出C++編譯器是怎麼在C語言的基礎上加入引用機制的。

        四、C++編譯器在C語言的基礎上加入引用機制

    

    說明:一、聲明引用時,C語言將引用聲明的是指針常量。(爲啥要初始化引用緣由)

               二、引用使用,C語言隱藏了對常指針自動間接引用,讓咱們徹底不用瞭解指針

               三、初始化引用時,C語言隱藏了對變量的取地址符&操做,讓咱們感受是在直接給變量起別名

    應用的剖析到此就結束了,下面咱們來講說匿名對象吧。

 

什麼是匿名對象

    匿名對象能夠理解爲是一個臨時對象,通常系統自動生成的,如你的函數返回一個對象,這個對象在返回時會生成一個臨時對象。

匿名對象的生命週期(很重要!!!)

class Cat
{
public:
	Cat()
	{
		cout<<"Cat類 無參構造函數"<<endl;
	}

	Cat(Const Cat& obj)
	{
		cout<<"Cat類 拷貝構造函數"<<endl;
	}

	~Cat()
	{
		cout<<"Cat類 析構函數 "<<endl;
	}

};

void playStage() //一個舞臺,展現對象的生命週期
{
	Cat();             /*在執行此代碼時,利用無參構造函數生成了一個匿名Cat類對象;執行完此行代碼,
	                        由於外部沒有接此匿名對象的變量,此匿名又被析構了*/
	Cat cc = Cat();    /*在執行此代碼時,利用無參構造函數生成了一個匿名Cat類對象;而後將此匿名變
	                        成了cc這個實例對象,此匿名對象沒有被析構。*/
	cout<<"cc 對象好沒有被析構"<<endl;    
}

int main()
{
	playStage();
	system("pause");
	return 0;
}

    輸出:

Cat類 無參構造函數
Cat類 析構函數
Cat類 無參構造函數
cc 對象好沒有被析構
Cat類 析構函數

    說明:一、在執行playStage( )函數中的Cat( )時,生成了一個匿名對象,執行完Cat( )代碼後,此匿名對象就此

             消失。這就是匿名對象的生命週期。

             二、在執行playStage( )函數中Cat cc = Cat();時,首先生成了一個匿名對象,由於外部有cc對象在等待被

             實例化,而後將此匿名對象變爲了cc對象,其生命週期就變成了cc對象的生命週期。

    總結:若是生成的匿名對象在外部有對象等待被其實例化,此匿名對象的生命週期就變成了外部對象的生命週期

              若是生成的匿名對象在外面沒有對象等待被其實例化,此匿名對象將會生成以後,立馬被析構

 最後但願能對你們有幫助,沙米才疏學淺,有什麼錯誤請留言指正,謝謝你們。

相關文章
相關標籤/搜索