當(dāng)前位置:首頁 > 芯聞號 > 充電吧
[導(dǎo)讀]一.聲明(Declaration)? ? ? ?聲明的作用是指定變量的類型和名稱,makes a name known to the program。區(qū)分聲明和定義可以讓C++支持分開編譯,比如A.c

一.聲明(Declaration)
? ? ? ?聲明的作用是指定變量的類型和名稱,makes a name known to the program。區(qū)分聲明和定義可以讓C++支持分開編譯,比如A.cpp中定義了變量var1,在B.cpp中只需要聲明var1這個變量就可以直接使用。因?yàn)檫@樣的用法,聲明常常見于頭文件中。源文件包含頭文件之后,就可以使用這個變量,即使沒有看到該變量的定義。 聲明的語法如下:

extern?int?i;?//?object?declaration
int?numDigits(int?number);?//?function?declaration
class?Widget;?//?class?declaration

template//?template?declaration
class?GraphNode;

extern?double?pi?=?3.1416;?//?definition

二.定義(Definition)
? ? ? ?定義是為變量分配存儲空間,并可能進(jìn)行初始化。定義是一種聲明,因?yàn)槎x的同時必然會指定變量的類型和名稱,然而聲明卻不是定義。C++中變量的定義必須有且僅有一次,而變量的聲明可以多次。變量一般不能定義在頭文件中,除了const變量(local to a file)。
? ? ? ?除了變量,類和函數(shù)也有定義的說法,總結(jié)如下:
1.對于類來說,一般定義在頭文件中。因?yàn)榫幾g器需要在每個源文件都看到類的定義才能編譯成功;
2.對于一般函數(shù)來說,函數(shù)聲明在頭文件中,函數(shù)定義則在源文件中;
3.對于inline和constexpr function,編譯器需要在每個源文件都看到定義,因此通常也定義在頭文件中。

int?x;?//?declaration?or?definition

? ? ? ?上面單獨(dú)的一行,是聲明還是定義,判斷的原則是看是否占用內(nèi)存(能否進(jìn)行初始化)。例如:

class?MyClass?//?類定義
{
???int?x;?//?它是聲明,以為C++11之前是不允許在類的定義內(nèi)部直接初始化數(shù)據(jù)成員的?
???float?y?=?10.0f;?//?C++11及以后支持這種寫法,但它仍然是個聲明
???static?char?c;???//?這也是個聲明,因?yàn)槿绻麑懗蛇@樣?static?char?c?=?'A';
????????????????????//?編譯器會報(bào)錯,你需要在類外進(jìn)行定義并初始化,因?yàn)轭惱锩娴闹皇锹暶鞫?};

? ? ? ?但是如果int x;出現(xiàn)在函數(shù)定義內(nèi)部,它就是一個定義了。例如:

int?nurnDigits(int?number)?//?function?definition
{
????int?x;?//?object?definition,因?yàn)榇藭rx是可以被初始化或賦值的
????x?=?number/10;
????return?x;
}
class?Widget?//?class?definition
{?
public:
????Widget();?//?function?declaration
????~Widget();
private:
????int?x;?//?object?declaration
????int?y;
}
template//?template?definition
class?GraphNode?
{
public:
????GraphNode();
????~GraphNode();
????......
}

? ? ? ?這里有一個令人疑惑的地方,頭文件的的類MyClass既然是定義,按照“定義”的解釋,它應(yīng)該占有內(nèi)存,那為何類中包含的內(nèi)容反而是聲明。
? ? ? ?因?yàn)轭愂菍儆谟脩糇远x的數(shù)據(jù)類型,與內(nèi)置類型,比如說int,在使用上類似。類定義只是定義了一種類型,也即說明了一個類,并沒有實(shí)際定義類的對象,定義的是類,定義類描述的是新的類型,而描述新類型并不會開辟內(nèi)存空間去存儲這樣一種新類的對象。
三.初始化(Initialization)

? ? ? ?初始化是指變量在創(chuàng)建的同時獲得的初始值。雖然C++經(jīng)常用=來初始化一個變量,但是賦值和初始化是兩種不同的操作。賦值是變量定義后的操作,效果是改變變量的值,或者說是用新值來替換舊值;而初始化是在變量創(chuàng)建期獲得一個值。兩者具有本質(zhì)的區(qū)別。下面分別介紹一下C++常見的初始化方式:

default initialization

? ? ? ?當(dāng)我們定義一個變量時,不提供initializer,那么這個變量就是默認(rèn)初始化(default initialized)的。默認(rèn)值由變量的類型和變量的定義位置來決定。
對于built-in type,默認(rèn)值由變量的定義位置決定。在函數(shù)外部定義的全局變量(global variable),函數(shù)內(nèi)部定義的局部靜態(tài)變量(local static object)全部初始化為0。函數(shù)內(nèi)部定義的局部變量是未初始化的;使用未初始化的變量值的行為是未定義的,會帶來巨大的潛在風(fēng)險(xiǎn)。

? ? ? ?對于class type,由類里的默認(rèn)構(gòu)造函數(shù)初始化。如果類定義里沒有默認(rèn)構(gòu)造函數(shù)(顯示或隱示),則編譯出錯。

#includeusing?namespace?std;

int?a;

int?main()
{
???static?int?b;
???int?c;

???cout?<<?a?<<?endl;
???cout?<<?b?<<?endl;
???cout?<<?c<<?endl;
???system("pause");
???return?0;
}

? ? ? ?在VS執(zhí)行這段代碼,輸出變量a的值0,b的值為0,同時VS會報(bào)錯:Run-Time Check Failure #3 — The variable 'c' is being used without being initialized。 變量a和b被默認(rèn)初始化為0,變量c未被初始化。

list initialization

? ? ? ?C++11中提供了一種新的初始化方式,list initialization,以大括號包圍。A tour of c++中寫到The = form is traditional and dates back to C, but if in doubt, use the general {}-list form。注意這種初始化方式要求提供的初始值與要初始化的變量類型嚴(yán)格統(tǒng)一,用法如下,

//?built-in?type?initialization
double?d1{2.3};????//ok:?direct-list-initialization?
double?d2?=?{2.3};?//ok:?copy-list-initialization
//?class?type?initialization
complexz2{d1,d2};
complexz3?=?{1,2};??//ok:?the?=?is?optional?with?{...}
vectorvec{1,2,3,4,5,6};//ok:?a?vector?of?ints

long?double?pi?=?3.1415;
int?a{pi},?b?=?{pi};?????????//error:?narrowing?conversion?required
int?c(pi),?d?=?pi;	?????//ok:?implict?conversion.

value initialization
? ? ? ?value initialization里,built-in type變量被初始化為0,class type的對象被默認(rèn)構(gòu)造(一定要有)初始化。這種方式通常見于STL里的vector和數(shù)組,且經(jīng)常與list initialization結(jié)合起來使用,為我們初始化全0數(shù)組提供了很大的便利。簡單用法如下:

vectorivec(10);			//ten?elements,?each?initialized?to?0
vectorsvec(10);		//ten?elmenets,?each?an?empty?string
vectorv1?=?{"a",?"an",?"the"};?//list?initialized
int?a[10]?=?{};				//ten?elements,?each?initialized?to?0
int?a2[]?=?{1,2,3};			//list?initialized
int?a3[5]?=?{1,2,3};			//equivalent?to?a3[]?=?{1,2,3,0,0}

關(guān)于類的初始化比較復(fù)雜,整理幾點(diǎn):
1.編譯器首先編譯類成員的聲明,包括函數(shù)和變量
2.整個類可見后,才編譯函數(shù)體(所以不管定義順序,函數(shù)里可以用類里的任何變量和函數(shù))
3.C++11提供了in-class initializers機(jī)制,C++ Primer里面講如果編譯器支持,推薦使用in-class initializers機(jī)制。注意這種機(jī)制只支持=,{}形式,不支持()。Constructor Initializer List對變量進(jìn)行初始化后,才進(jìn)入構(gòu)造函數(shù)。Constructor Initializer List里忽略的成員變量(為空則相當(dāng)于全部忽略),會由in-class initializers初始化,或者采取default initialization,然后進(jìn)入構(gòu)造函數(shù)體,構(gòu)造函數(shù)體實(shí)際是給成員二次賦值
4.對于class type成員,會調(diào)用其默認(rèn)構(gòu)造函數(shù)進(jìn)行default initialization。

5.對于built-in type成員,要么in-class initialization,要么Constructor initializer list。是否會被default initialization與類定義的位置有關(guān),這點(diǎn)和“default initialization”小節(jié)中說的built-int type類似

6.類的靜態(tài)函數(shù)成員可以在類內(nèi)部或者外部定義,而靜態(tài)數(shù)據(jù)成員(const除外)則只能在外部定義以及初始化

#includeusing?namespace?std;

class?testA
{
public:
	testA()
	{
		cout?<<?"A-x:"?<<?x?<<?endl;
		cout?<<?"A-y:"?<<?y?<<?endl;
	}
private:
	int?x;
	int?y?=?10;?//?in-class?initializer
};

class?testB
{
public:
	void?printf()?const
	{
		cout?<<?"B:"?<<?data?<<?endl;
	}
private:
	int?data;
	testA?a;
};

testB?b1;

int?main()
{
	b1.printf();
	testB?b2;
	b2.printf();

	system("pause");
	return?0;
}

如果是動態(tài)初始化的對象,輸出結(jié)果和上圖一樣,代碼如下:

#includeusing?namespace?std;

class?testA
{
public:
	testA()
	{
		cout?<<?"A-x:"?<<?x?<<?endl;
		cout?<<?"A-y:"?<<?y?<<?endl;
	}
private:
	int?x;
	int?y?=?10;?//?in-class?initializer
};

class?testB
{
public:
	void?printf()?const
	{
		cout?<<?"B:"?<<?data?<<?endl;
	}
private:
	int?data;
	testA?a;
};

testB?*b1=new?testB();

int?main()
{
	b1->printf();
	testB?*b2?=?new?testB;
	b2->printf();

	system("pause");
	return?0;
}

? ? ? ?但是如果在main函數(shù)中,對b2進(jìn)行value initialization,即將testB *b2 =new testB;改成testB *b2 =new testB();,那么類中的built-in type成員都會被default initialization了。輸出結(jié)果如下所示:


? ? ? ?還需注意的是數(shù)組的初始化。

? ? ? ?定義數(shù)組時,如果沒有顯示提供初始化列表,則數(shù)組元素的默認(rèn)化初始規(guī)則同普通變量一樣:函數(shù)體外定義的內(nèi)置類型數(shù)組,其元素初始為0;函數(shù)體內(nèi)定義的內(nèi)置類型數(shù)組,其元素?zé)o初始化;類類型數(shù)組無論在哪里定義,皆調(diào)用默認(rèn)構(gòu)造函數(shù)進(jìn)行初始化,無默認(rèn)構(gòu)造函數(shù)則必須提供顯示初始化列表。
? ? ? ?如果定義數(shù)組時,僅提供了部分元素的初始列表,其剩下的數(shù)組元素,若是類類型則調(diào)用默認(rèn)構(gòu)造函數(shù)進(jìn)行初始,若是內(nèi)置類型則初始為0(不論數(shù)組定義位置)。
? ? ? ?對于動態(tài)分配的數(shù)組,如果數(shù)組元素是內(nèi)置類型,其元素?zé)o初始化;如果數(shù)組元素是類類型,依然調(diào)用默認(rèn)構(gòu)造函數(shù)進(jìn)行初始化。也可以在使用跟在數(shù)組長度后面的一對空圓括號對數(shù)組元素做值初始化。
例如: int *ptrA = new int[10];
    int *ptrB = new int[10] ();
? ? ? ?其中ptrA指向的動態(tài)數(shù)組其元素未初始化,而ptrB指向的動態(tài)數(shù)組元素被初始化為0。

四.賦值(Assignment)?
? ? ? ?賦值的結(jié)果是左邊的操作元,為左值,也就是說,下面的寫法語法正確

int?a?=?0;
(a?=?0)?=?1;?//?the?final?value?of?a?is?1

? ? ? ?因?yàn)橘x值操作符的優(yōu)先級很低,該帶括號的時候不能遺漏。
? ? ? ?順便提一下++i和i++的區(qū)別:前者將操作元增加,并且返回改變后的操作元;后者將操作數(shù)增加,返回原先值得拷貝作為結(jié)果。前置自增返回的結(jié)果是左值,后置自增返回的是右值。前置自增操作符做的無用功少,雖然C++編譯器對int和指針類型的后置自增操作符作了優(yōu)化,C++ Primer推薦如無特殊需求,優(yōu)先使用前置自增操作符。

? ? ? ?數(shù)組不支持拷貝初始化或者將一個整體賦值給另一個數(shù)組。

int?a[]?=?{0,1,2}?int?a2[]?=?a;?//?error:?cannot?assign?one?array?to?another



本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉