C++存儲(chǔ)鏈接性原理詳解
鏈接性
鏈接性是指名稱在不同文件之間能否共享,而作用域是指名稱在文件內(nèi)部哪些范圍可見(jiàn)。
這里的文件并非開(kāi)發(fā)時(shí)創(chuàng)建的文件,而是將文件的 include 內(nèi)容全部遞歸包含進(jìn)來(lái)之后,形成的大文件。
這一點(diǎn)也是與Go等一些語(yǔ)言不同。在Go語(yǔ)言中,文件是按包(package)組織,所有依賴的包都需要直接或間接import進(jìn)來(lái)。也就是從main開(kāi)始遞歸import得到的就是我們依賴的所有文件。
但C++不同。C++源文件主要分.h 和 .cpp兩種,一般我們都只會(huì)include .h文件,而不會(huì)include .cpp文件。因此,.cpp文件之間其實(shí)沒(méi)有直接關(guān)聯(lián),需要通過(guò)cmakelist等方式告訴編譯器,我們的程序涉及到哪些源文件。
而C++在編譯時(shí),會(huì)首先將include的文件內(nèi)容全部遞歸包含進(jìn)來(lái),形成一個(gè)大的文件,這個(gè)大文件是一個(gè)編譯單元,也就是上面鏈接性所說(shuō)的文件。其實(shí),C++的宏定義的可使用范圍,也是在這個(gè)大文件內(nèi)。
鏈接性有三種:
- 外部鏈接性:一個(gè)文件聲明的名稱可以在另一個(gè)文件中使用
- 內(nèi)部鏈接性:聲明的名稱只能在文件內(nèi)使用
- 無(wú)鏈接性:意味著只能在函數(shù)或代碼塊內(nèi)使用
自動(dòng)類型變量都沒(méi)有鏈接性,而靜態(tài)類型變量可以有三種鏈接性。那么如何定義這三種鏈接性的靜態(tài)變量呢?
外部鏈接性
鏈接性為外部的變量也叫外部變量,也稱全局變量。外部變量在函數(shù)外聲明,不加static關(guān)鍵字。外部變量可以在所有文件使用。
對(duì)于函數(shù)來(lái)說(shuō),沒(méi)有加inline和static關(guān)鍵字的函數(shù),都具有外部鏈接性。
說(shuō)到外部,可能會(huì)想到一個(gè)關(guān)鍵字:extern。這個(gè)關(guān)鍵字有什么用?實(shí)際上它是用來(lái)做引用聲明。因?yàn)槿绻胧褂闷渌募卸x的外部變量,不能直接使用,而是要先進(jìn)行引用聲明,表示要引用這個(gè)外部變量,這里就需要用到關(guān)鍵字extern。例如:
// file1.cpp int foo = 1; // file2.cpp extern int foo; // extern int foo = 1; WRONG cout << foo;
file1.cpp 在函數(shù)之外定義了全局變量foo,在file2.cpp中,用extern關(guān)鍵字聲明之后,即可使用foo了。注意,extern語(yǔ)句中不能初始化foo,否則這里就變成定義而不是引用聲明,導(dǎo)致重復(fù)定義全局變量foo,編譯錯(cuò)誤。
單定義規(guī)則
對(duì)于外部變量,每個(gè)使用它的文件都必須聲明它。而C++又有“單定義規(guī)則”,即鏈接性為外部的函數(shù)和變量可以有多個(gè)聲明,但只能有一個(gè)定義。這里再明確下這兩個(gè)術(shù)語(yǔ):“定義聲明”,簡(jiǎn)稱“定義”;“引用聲明”,簡(jiǎn)稱“聲明”。
為了實(shí)現(xiàn)單定義規(guī)則,編譯器要知道這一行代碼是在聲明還是在定義,那怎么區(qū)分聲明還是定義呢?
對(duì)于函數(shù)來(lái)說(shuō),區(qū)分聲明和定義很簡(jiǎn)單,有函數(shù)體則是定義,否則為聲明。而變量則不同,前面所謂的變量聲明,對(duì)于編譯器來(lái)說(shuō)都是定義,都分配了存儲(chǔ)空間。如何聲明一個(gè)變量而不分配存儲(chǔ)空間呢?關(guān)鍵字extern就派上用場(chǎng)了,使用extern關(guān)鍵字且沒(méi)有進(jìn)行初始化,則為聲明,不會(huì)分配存儲(chǔ)空間,否則為定義。
C++初學(xué)者可能還不太明白為什么C++中都要把函數(shù)聲明放在.h文件,把函數(shù)定義放在.cpp文件中。其實(shí)用單定義規(guī)則就很好解釋了。函數(shù)如果沒(méi)有加inline和static,即具有外部鏈接性,如果把定義放在.h文件中,這個(gè).h文件會(huì)被多個(gè).cpp文件引用,編譯時(shí)會(huì)形成多個(gè)副本,相當(dāng)于被定義了多次。
總之,.h文件中只能放聲明,或者沒(méi)有外部鏈接性的定義。
可能有小伙伴發(fā)現(xiàn),有些定義在函數(shù)外的靜態(tài)變量沒(méi)有加static,也會(huì)放在.h文件中,為什么可以呢?其實(shí)const變量默認(rèn)會(huì)添加static,鏈接性變?yōu)閮?nèi)部。而如果想要聲明為外部變量,則需要加上external:
const int foo = 10; // 鏈接性為內(nèi)部 extern const int bar = 10; // 鏈接性為外部
內(nèi)部鏈接性
前面說(shuō)了,定義在函數(shù)外部的變量默認(rèn)是全局變量,具有外部鏈接性。但如果加上static說(shuō)明符,則變成內(nèi)部鏈接性。對(duì)于函數(shù)也一樣,加上static則變?yōu)閮?nèi)部鏈接性。
在函數(shù)外定義的變量,static的含義與局部變量中static的含義不同。前者表示鏈接性為內(nèi)部,后者表示存儲(chǔ)持續(xù)性為靜態(tài)。這也可以稱為關(guān)鍵字重載,即關(guān)鍵字在不同上下文中有不同含義。
具有內(nèi)部鏈接性的變量或函數(shù),可以在不同文件中有多個(gè)定義。內(nèi)部鏈接性的變量也可以與同名外部變量同時(shí)存在,這時(shí)內(nèi)部變量將隱藏外部變量。對(duì)函數(shù)來(lái)說(shuō)也一樣。
無(wú)鏈接性
定義在函數(shù)或代碼塊內(nèi)的局部變量沒(méi)有鏈接性,只能在局部使用。如果加上static修飾則為靜態(tài)變量,雖然在程序運(yùn)行期間會(huì)一直存在,但只有在代碼塊內(nèi)才能使用。
總結(jié)
下面總結(jié)一下前面提到的不同存儲(chǔ)持續(xù)性與鏈接性的變量。
- 自動(dòng)存儲(chǔ)持續(xù)性,無(wú)鏈接性
在代碼塊內(nèi)定義
- 靜態(tài)存儲(chǔ)持續(xù)性,無(wú)鏈接性
在代碼塊內(nèi)定義,用static關(guān)鍵字
- 靜態(tài)存儲(chǔ)持續(xù)性,內(nèi)部鏈接性
在代碼塊外定義,用static關(guān)鍵字 或const修飾
- 靜態(tài)存儲(chǔ)持續(xù)性,外部鏈接性
在代碼塊外定義。引用聲明則需要用extern
以上就是C++存儲(chǔ)鏈接性原理示例詳解的詳細(xì)內(nèi)容,更多關(guān)于C++存儲(chǔ)鏈接性原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++版本基于ros將文件夾中的圖像轉(zhuǎn)換為bag包
這篇文章主要介紹了C++版本基于ros將文件夾中的圖像轉(zhuǎn)換為bag包,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-01-01win10環(huán)境下vscode Linux C++開(kāi)發(fā)代碼自動(dòng)提示配置(基于WSL)
這篇文章主要介紹了win10環(huán)境下vscode Linux C++開(kāi)發(fā)代碼自動(dòng)提示配置(基于WSL),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05C語(yǔ)言實(shí)現(xiàn)2D賽車游戲的示例代碼
此游戲是《2D 賽車》的”魔改版“——2.5D 雙人賽車!原作實(shí)現(xiàn)了 2D 視角的賽車游戲,但是我覺(jué)得不夠真實(shí)、操縱感不強(qiáng),故擠出數(shù)個(gè)周末完成了這個(gè)”魔改版“,實(shí)現(xiàn)了第一人稱的視角,希望大家喜歡2022-12-12使用C++11實(shí)現(xiàn)Android系統(tǒng)的Handler機(jī)制
這篇文章主要介紹了使用C++11實(shí)現(xiàn)Android系統(tǒng)的Handler機(jī)制,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04c++ 連接兩個(gè)字符串實(shí)現(xiàn)代碼 實(shí)現(xiàn)類似strcat功能
c++ 連接兩個(gè)字符串實(shí)現(xiàn)代碼 實(shí)現(xiàn)類似strcat功能,需要的朋友可以參考下2012-05-05C++ 二維(多維)vector添加一個(gè)空項(xiàng)問(wèn)題
這篇文章主要介紹了C++ 二維(多維)vector添加一個(gè)空項(xiàng)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11用c語(yǔ)言實(shí)現(xiàn)HUP信號(hào)重啟進(jìn)程的方法
本篇文章是對(duì)使用c語(yǔ)言實(shí)現(xiàn)HUP信號(hào)重啟進(jìn)程的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05