pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

C++內(nèi)存模型和名稱空間詳解

這篇文章主要給大家介紹了關(guān)于C/C++中的內(nèi)存模型和名稱空間詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用c/c++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來

本章內(nèi)容包括:

  • 單獨(dú)編譯
  • 存儲(chǔ)持續(xù)性、作用域和鏈接性
  • 定位new運(yùn)算符
  • 名稱空間

1. 單獨(dú)編譯

和C語言一樣,C++允許甚至鼓勵(lì)程序員將組件放在獨(dú)立的文件中。可以單獨(dú)編譯這些文件,然后將它們連接成可執(zhí)行程序。(通常,C++編譯器即編譯程序,也管理連接器)。如果只修改了一個(gè)文件,則可以只重新編譯該文件,然后將它與其他文件的編譯版本鏈接。這使得大程序的管理更便捷。

C++開發(fā)人員使用 #include 導(dǎo)入頭文件,與其將結(jié)構(gòu)聲明加入到每一個(gè)文件中,不如將其放在頭文件中,然后在每一個(gè)源代碼文件中包含該頭文件。這樣,要修改結(jié)構(gòu)聲明時(shí),只需在頭文件中做一次改動(dòng)即可。另外,可以將函數(shù)原型放在頭文件中。因此,可以將原來的程序分成三部分。

  • 頭文件:包含結(jié)構(gòu)聲明和使用這些結(jié)構(gòu)的函數(shù)的原型
  • 源代碼文件:包含與結(jié)構(gòu)有關(guān)的函數(shù)的代碼
  • 源代碼文件:包含調(diào)用與結(jié)構(gòu)相關(guān)的函數(shù)的代碼

請(qǐng)不要將函數(shù)定義或變量聲明放到頭文件中。這樣做對(duì)簡(jiǎn)單情況可能是可行的,但通常會(huì)引來麻煩。例如,如果在頭文件包含一個(gè)函數(shù)定義,然后在其他兩個(gè)文件中包含該頭文件,則同一個(gè)程序中將包含同一個(gè)函數(shù)的兩個(gè)定義,除非函數(shù)是內(nèi)聯(lián)的,否則將會(huì)出錯(cuò)。下面列出了頭文件中常包含的內(nèi)容。

  • 函數(shù)原型
  • 使用#define或const定義的符號(hào)常量
  • 結(jié)構(gòu)聲明
  • 類聲明
  • 模板聲明
  • 內(nèi)聯(lián)函數(shù)

將結(jié)構(gòu)聲明放在頭文件中是可以的,因?yàn)樗鼈儾粍?chuàng)建變量,而只是在源代碼文件中聲明結(jié)構(gòu)變量時(shí),告訴編譯器如何創(chuàng)建該結(jié)構(gòu)變量。同樣,模板聲明不是將被編譯的代碼,它們指示編譯器如果和生成與源代碼中的函數(shù)調(diào)用相匹配的函數(shù)定義。被聲明為const的數(shù)據(jù)和內(nèi)聯(lián)函數(shù)有特殊的鏈接屬性,因此可以將其放在頭文件中,而不會(huì)引起問題。

頭文件管理

在同一個(gè)文件中只能將同一個(gè)頭文件包含一次。有一種標(biāo)準(zhǔn)的C/C++技術(shù)可以避免多次包含同一個(gè)頭文件。它是基于預(yù)處理器編譯指令 #ifndef (即 if not defined)的。下面代碼片段意味著僅當(dāng)以前沒有使用預(yù)處理器編譯指令#define定義名稱COORDIN_H_時(shí),才處理 #ifndef 和 #endif之間的語句:


#ifndef COORDIN_H_
...
#endif

通常,使用#define語句來創(chuàng)建符號(hào)常量,如下所示:


#define MAXIMUM 4096

但只要將#define用于名稱,就足以完成該名稱的定義,如下所示:


#ifndef COORDIN_H_
#define COORDIN_H_
// place include file contents here
#endif

多個(gè)庫(kù)的鏈接

C++標(biāo)準(zhǔn)允許每個(gè)編譯器設(shè)計(jì)人員以他認(rèn)為合適的方式實(shí)現(xiàn)名稱修飾,因此由不同編譯器創(chuàng)建的二進(jìn)制模塊(對(duì)象代碼文件)很可能無法正確地鏈接。也就是說,兩個(gè)編譯器將為同一個(gè)函數(shù)生成不同的修飾名稱。名稱的不同將使鏈接器無法將一個(gè)編譯器生成的函數(shù)調(diào)用與另一個(gè)編譯器生成的函數(shù)定義匹配。在鏈接編譯模塊時(shí),請(qǐng)確保所有對(duì)象文件或庫(kù)都是由同一個(gè)編譯器生成的。如有源代碼,通??梢杂米约旱木幾g器重新編譯源代碼來消除鏈接錯(cuò)誤。

2.存儲(chǔ)持續(xù)性、作用域和鏈接性

接下來擴(kuò)展存儲(chǔ)類別如何影響信息在文件間的共享。C++使用三種(在C++11中是四種)不同的方案來存儲(chǔ)數(shù)據(jù),這些方案的區(qū)別就在于數(shù)據(jù)保留在內(nèi)存中的時(shí)間。

  • 自動(dòng)存儲(chǔ)持續(xù)性:在函數(shù)定義中聲明的變量(包括函數(shù)參數(shù))的存儲(chǔ)持續(xù)性為自動(dòng)的。它們?cè)诔绦蜷_始執(zhí)行其所屬的函數(shù)或代碼塊時(shí)被創(chuàng)建,在執(zhí)行完函數(shù)或代碼塊時(shí),它們使用的內(nèi)存被釋放。C++有兩種存儲(chǔ)持續(xù)性為自動(dòng)的變量。
  • 靜態(tài)存儲(chǔ)持續(xù)性:在函數(shù)定義外定義的變量和使用關(guān)鍵字static定義的變量的存儲(chǔ)持續(xù)性都為靜態(tài)。它們?cè)诔绦蛘麄€(gè)運(yùn)行過程中都存在。C++有3中存儲(chǔ)持續(xù)性為靜態(tài)的變量。
  • 線程存儲(chǔ)持續(xù)性:當(dāng)前,多核處理器很常見,這些CPU可同時(shí)處理多個(gè)執(zhí)行任務(wù)。這讓程序能夠?qū)⒂?jì)算放在可并行處理的不同線程中。如果變量是使用關(guān)鍵字thread_local聲明的,則其聲明周期與所屬的線程一樣長(zhǎng)。
  • 動(dòng)態(tài)存儲(chǔ)持續(xù)性:用new運(yùn)算符分配的內(nèi)存將一直存在,直到使用delete運(yùn)算符將其釋放或程序結(jié)束為止。這種內(nèi)存的存儲(chǔ)持續(xù)性為動(dòng)態(tài),有時(shí)被稱為自由存儲(chǔ)或堆。

2.1 作用域和鏈接

作用域描述了名稱在文件的多大范圍內(nèi)可見。例如,函數(shù)中定義的變量可在該函數(shù)中使用,但不能在其他函數(shù)中使用;而在文件中的函數(shù)定義之前定義的變量則可在所有函數(shù)中使用。鏈接性(linkage)描述了名稱如何在不同單元間共享。鏈接性為外部的名稱可在文件間共享,鏈接性為內(nèi)部的名稱只能由一個(gè)文件中的函數(shù)共享。自動(dòng)變量的名稱沒有鏈接性,因?yàn)樗鼈儾荒芄蚕怼?/p>

C++變量的作用域有多種。作用域?yàn)榫植康淖兞恐辉诙x它的代碼塊中可用,代碼塊是由花括號(hào)括起的一系列語句。

C++函數(shù)的作用域可以是整個(gè)類或整個(gè)名稱空間(包括全局的),但不能是局部的(因?yàn)椴荒茉诖a塊內(nèi)定義的函數(shù),如果函數(shù)的作用域?yàn)榫植?,則只對(duì)它自己是可見的,因此不能被其他函數(shù)調(diào)用。這樣的函數(shù)將無法運(yùn)行)。

2.2 自動(dòng)存儲(chǔ)持續(xù)性

默認(rèn)情況下,在函數(shù)中聲明的函數(shù)參數(shù)和變量的存儲(chǔ)持續(xù)性為自動(dòng),作用域?yàn)榫植浚瑳]有鏈接性。也就是說,如果main()中聲明了一個(gè)名為texas的變量,并在函數(shù)oil()中也聲明了一個(gè)名稱texas的變量,則創(chuàng)建了兩個(gè)獨(dú)立的變量——只有在定義他們的函數(shù)中才能使用它們。堆iol()的texas執(zhí)行的任何操作都不會(huì)影響main()中的texas,反之亦然。另外,當(dāng)程序開始執(zhí)行這些變量所屬的代碼塊時(shí),將為其分配內(nèi)存;當(dāng)函數(shù)結(jié)束時(shí),這些變量都將消失。

使用C++11中的auto

在C++11中,關(guān)鍵字auto用于自動(dòng)類型推斷。但在C語言和以前的C++版本中,auto的含義截然不同,它用于顯式地指出變量為自動(dòng)存儲(chǔ):


int froob(int n)
{
    auto float ford; //ford has automatic stroage
    ...
}

由于只能將關(guān)鍵字用于默認(rèn)為自動(dòng)的變量,因此程序員幾乎不使用它。它的主要用途是指出當(dāng)前變量為局部自動(dòng)變量。在C++11中,這種用法不再合法。

1,自動(dòng)變量的初始化

可以使用任何在聲明時(shí)其值已知的表達(dá)式來初始化自動(dòng)變量,下面的示例初始化變量x,y,z:


int w;
int x=5;
int big =INT_MAX -1;
int y=x *x;
int y=2*x;
cin>>w;
int z=3*w;

2,自動(dòng)變量的初始化

了解典型的C++編譯器如何實(shí)現(xiàn)自動(dòng)變量有助于更深入地了解自動(dòng)變量。由于自動(dòng)變量的數(shù)目隨函數(shù)的開始和結(jié)束而增減,因此程序必須在運(yùn)行時(shí)對(duì)自動(dòng)變量進(jìn)行管理。常用的方法是留出一段內(nèi)存,并將其視為棧,以管理變量的增減。之所以被稱為棧,是由于新數(shù)據(jù)被象征性地放在原有數(shù)據(jù)的上面(也就是說,在相鄰的內(nèi)存單元中,而不是在同一個(gè)內(nèi)存單元中),當(dāng)程序使用完后,將其從棧中刪除。棧的默認(rèn)長(zhǎng)度取決于實(shí)現(xiàn),但編譯器通常提供改變棧長(zhǎng)度的選項(xiàng)。程序使用兩個(gè)指針來跟蹤棧,一個(gè)指針指向棧底——棧的開始位置,另一個(gè)指針指向堆頂——下一個(gè)可用內(nèi)存單元。當(dāng)函數(shù)被調(diào)用時(shí),其自動(dòng)變量被加入到棧中,棧頂指針指向變量后面的下一個(gè)可用的內(nèi)存單元。函數(shù)結(jié)束時(shí),棧頂指針被重置為函數(shù)被調(diào)用前的值,從而釋放新變量使用的內(nèi)存。

棧時(shí)LIFO(后進(jìn)先出)的,即最后加入到棧中的變量首先被彈出。這種設(shè)計(jì)簡(jiǎn)化了參數(shù)傳遞。函數(shù)調(diào)用將其參數(shù)的值放在棧頂,然后重新設(shè)置棧頂指針。被調(diào)用的函數(shù)根據(jù)其形參描述來確定每個(gè)參數(shù)的地址。下圖中,函數(shù)fib()被調(diào)用時(shí),傳遞一個(gè)2字節(jié)的int和一個(gè)4字節(jié)的long。這些值被加入到棧中。當(dāng)fib()開始執(zhí)行時(shí),它將real和tell同這兩個(gè)值關(guān)聯(lián)起來。當(dāng)fib()結(jié)束時(shí),棧頂指針重新指向以前的位置。新值沒有被刪除,但不再被標(biāo)記,它們所占據(jù)的空間將被下一個(gè)將值加入到棧中的函數(shù)調(diào)用所使用。

3,寄存器變量

關(guān)鍵字register最初是由C語言引入的,它建議編譯器使用CPU寄存器來存儲(chǔ)自動(dòng)變量:


register int count_fast; //request for a rregister variable

這旨在提高訪問變量的速度。

在C++11之前,這個(gè)關(guān)鍵字在C++中的用法始終未變,只是隨著硬件和編譯器變得越來越復(fù)雜,這種提示表明變量用的很多,編譯器可以對(duì)其做特殊處理。在C++11中,這種提示作用也失去了,編輯案子register只是顯式地指出變量是自動(dòng)的。鑒于關(guān)鍵字register只能用于原本就是自動(dòng)的變量,使用它唯一的原因是,指出程序員想使用一個(gè)自動(dòng)變量,這個(gè)變量的名稱可能與外部變量相同。這與auto以前的用途完全相同。然而,保留關(guān)鍵字register的重要原因是,避免使用了該關(guān)鍵字的現(xiàn)有代碼非法。

2.3 靜態(tài)持續(xù)變量

和C語言一樣,C++也為靜態(tài)存儲(chǔ)持續(xù)性變量提供了3種鏈接性:外部鏈接性(可在其他文件中訪問)、內(nèi)部鏈接性(只能在當(dāng)前文件中訪問)和無鏈接性(只能在當(dāng)前函數(shù)或代碼塊中訪問)。這3種鏈接性都在整個(gè)程序執(zhí)行期間存在,與自動(dòng)變量相比,它們的壽命更長(zhǎng)。由于靜態(tài)變量的數(shù)目在程序運(yùn)行期間是不變的,因此程序不需要使用特殊的裝置(如棧)來管理它們。編譯器將分配固定的內(nèi)存塊來存儲(chǔ)所有的靜態(tài)變量,這些變量在整個(gè)程序執(zhí)行期間一直存在。另外,如果沒有顯式地初始化靜態(tài)變量,編譯器將把它設(shè)置為0。在默認(rèn)情況下,靜態(tài)數(shù)組和結(jié)構(gòu)將每個(gè)元素或成員的所有位都設(shè)置為0。

創(chuàng)建外部靜態(tài)持續(xù)變量,在代碼塊外面聲明它;

創(chuàng)建內(nèi)部的靜態(tài)持續(xù)變量,在代碼塊的外面聲明它,并使用static限定符;

創(chuàng)建無鏈接的靜態(tài)持續(xù)變量,在代碼塊中聲明它,并使用static限定符。


...
int global =1000;  // static duration, external linkage
static int one_file =50; //static duration, internal linkage
int main()
{
    ...
}
void funct1(int n)
{
    static int count =0; // static duration, no linkage
    int llama =0; 
}

所有的靜態(tài)持續(xù)變量都有下述初始化特征: 未被初始化的靜態(tài)變量的所有位都被設(shè)置為0。這種變量稱為零初始化的(zero-initialized)。

下表9.1總結(jié)了引入名稱空間之前使用的初始化特征。指出了關(guān)鍵字static的兩種用法,但含義有些不同:用于局部聲明,以指出變量是無鏈接性的靜態(tài)變量,static表示的是存儲(chǔ)持續(xù)性;而用于代碼塊外的聲明時(shí),static表示內(nèi)部鏈接性,而變量已經(jīng)是靜態(tài)持續(xù)性了。有人稱之為關(guān)鍵字重載,即關(guān)鍵字的含義取決于上下文。

2.4 靜態(tài)持續(xù)性、外部鏈接性

鏈接性為外部的變量通常稱為外部變量,它們的存儲(chǔ)持續(xù)性為靜態(tài),作用域?yàn)檎麄€(gè)文件。外部變量是在函數(shù)外部定義的,因此對(duì)所有函數(shù)而言都是外部的。例如,可以在main()前面或頭文件中定義它們??梢栽谖募形挥谕獠孔兞慷x后面的任何函數(shù)中使用它,因此外部變量也稱為全局變量。

1,單定義規(guī)則

一方面,在每個(gè)使用外部變量的文件中,都必須聲明它;另一方面,C++有“單定義規(guī)則”(One Definition Rule, ODR), 該規(guī)則指出,變量只能有一次定義。為滿足這種需求,C++提供了兩種變量聲明。一種是定義聲明或簡(jiǎn)稱定義,它給變量分配存儲(chǔ)空間;另一種是引用聲明或簡(jiǎn)稱聲明,它不給變量分配存儲(chǔ)空間,因?yàn)樗靡延械淖兞俊?/p>

引用聲明使用關(guān)鍵字extern,且不進(jìn)行初始化;否則,聲明為定義,導(dǎo)致分配存儲(chǔ)空間。


double up;  //definition, up is 0;
extern int blem;     //blem defined elsewhere
extern char gr ='z';  //definition because initialized

如果要在多個(gè)文件中使用外部變量,只需在一個(gè)文件中包含該變量的定義(單定義規(guī)則),但在使用變量的其他所有文件中,都必須使用關(guān)鍵字extern聲明它。

全局變量和局部變量

既然可以選擇使用全局變量或局部變量,那么到底應(yīng)使用哪種呢?首先,全局變量很有吸引力——因?yàn)樗械暮瘮?shù)能訪問全局變量,因此不用傳遞參數(shù)。但易于訪問的代價(jià)很大——程序不可靠。計(jì)算經(jīng)驗(yàn)表明,程序越能避免對(duì)數(shù)據(jù)進(jìn)行不必要的訪問,就越能保持?jǐn)?shù)據(jù)的完整性。通常情況下,應(yīng)使用局部變量,應(yīng)在需要知曉時(shí)才傳遞數(shù)據(jù),而不應(yīng)不加區(qū)分地使用全局變量來使數(shù)據(jù)可用。

2.5 靜態(tài)持續(xù)性、內(nèi)部鏈接性

將static限定符用于作用域?yàn)檎麄€(gè)文件的變量時(shí),該變量的鏈接性將為內(nèi)部的。在多文件程序中,內(nèi)部鏈接性和外部鏈接性之間的差別很有意義。鏈接性為內(nèi)部的變量只能在其所屬的文件中使用,但常規(guī)外部變量都具有外部鏈接性,即可以在其他文件中使用。

可使用外部變量在多文件程序的不同部分之間共享數(shù)據(jù);可使用鏈接性為內(nèi)部的靜態(tài)變量在同一個(gè)文件中的多個(gè)函數(shù)之間共享數(shù)據(jù)(名稱空間提供了另外一種共享數(shù)據(jù)的方法)。另外,如果將作用域?yàn)檎麄€(gè)文件的變量變?yōu)殪o態(tài)的,就不必?fù)?dān)心其名稱與其他文件中的作用域?yàn)檎麄€(gè)文件的變量發(fā)生沖突。

2.6 靜態(tài)存儲(chǔ)持續(xù)性、無鏈接性

無鏈接性的局部變量是這樣創(chuàng)建的,將static限定符用于在代碼塊中定義的變量。在代碼塊中使用static時(shí),將導(dǎo)致局部變量的存儲(chǔ)持續(xù)性為靜態(tài)的。這意味著雖然該變量只在該代碼塊中可用,但它在該代碼塊不處于活動(dòng)狀態(tài)時(shí)仍然存在。因此在兩次函數(shù)調(diào)用之間,靜態(tài)局部變量的值將保持不變。(靜態(tài)變量適用于再生)。另外,如果初始化了靜態(tài)局部變量,則程序只在啟動(dòng)時(shí)進(jìn)行一次初始化。以后再調(diào)用函數(shù)時(shí),將不會(huì)像自動(dòng)變量那樣再次被初始化。

2.7 說明符和限定符

有些被稱為存儲(chǔ)說明符或cv-限定符的C++關(guān)鍵字提供了其他有關(guān)存儲(chǔ)的信息。下面是存儲(chǔ)說明符:

  • auto(在C++11中不再是說明符)
  • register;
  • static
  • extern
  • thread_local(C++11新增的)
  • mutable

其中的大部分已經(jīng)介紹過了,在同一個(gè)聲明中不能使用多個(gè)說明符,但thread_local除外,它可與static或extern結(jié)合使用。前面講過,在C++11之前,可以在聲明中使用關(guān)鍵字auto指出變量為自動(dòng)變量;但在C++11中,auto用于自動(dòng)類型推斷。關(guān)鍵字register用于在聲明中指示寄存器存儲(chǔ),而在C++11中,它只是顯式地指出變量是自動(dòng)的。關(guān)鍵字static被用在作用域?yàn)檎麄€(gè)文件的聲明中時(shí),表示內(nèi)部鏈接性;被用于局部聲明中,表示局部變量的存儲(chǔ)持續(xù)性為靜態(tài)的。關(guān)鍵字extern表明是引用聲明,即聲明在其他地方定義的變量。關(guān)鍵字thread_local指出變量的持續(xù)性與其所屬線程的持續(xù)性相同。thread_local變量之于線程,猶如常規(guī)靜態(tài)變量之于整個(gè)程序。關(guān)鍵字mutable的含義將根據(jù)const來解釋,因此先來介紹cv-限定符,然后再解釋它。

1. cv-限定符

下面就是cv限定符

  • const
  • volatile

const是常見的cv-限定符,它表明,內(nèi)存被初始化后,程序便不能再對(duì)它進(jìn)行修改。

關(guān)鍵字volatile表明,即使程序代碼沒有對(duì)內(nèi)存單元進(jìn)行修改,其值也可能發(fā)生變化。聽起來似乎很神秘,實(shí)際上并非如此。例如,可以將一個(gè)指針指向某個(gè)硬件位置,其中包含了來自串行端口的時(shí)間或信息。在這種情況下,硬件(而不是程序)可能修改其中的內(nèi)容?;蛘邇蓚€(gè)程序可能互相影響,共享數(shù)據(jù)。該關(guān)鍵字的作用是改善編譯器的優(yōu)化能力。例如,假設(shè)編譯器發(fā)現(xiàn),程序在幾條語句中兩次使用了某個(gè)變量的值,則編譯器可能不是讓程序查找這個(gè)值兩次,而是將這個(gè)值緩存到寄存器中。這種優(yōu)化假設(shè)變量的值在這兩次使用之間不會(huì)變化。如果不將變量聲明為volatile,則編譯器將進(jìn)行這種優(yōu)化,將變量聲明為volatile,相當(dāng)于告訴編譯器,不要進(jìn)行這種優(yōu)化。

2. mutable

現(xiàn)在回到mutable??梢杂盟鼇碇赋?,即使結(jié)構(gòu)(或類)變量為const。其某個(gè)成員也可以被修改。例如:


struct data
{
    char name[30];
    mutable int accesses;
    ...
};
const data veep = {"Claybourne Clodde",0, ...};
strcpy(veep.name, "Joye Joux"); //not allowed
veep.accesses++;                //allowed

veep的const限定符禁止程序修改veep的成員,但access成員的mutable說明符使得access不受這種限制。

3. 再談const

在C++(但不是在C語言)中,const限定符對(duì)默認(rèn)存儲(chǔ)類型稍有影響。在默認(rèn)情況下全局變量的鏈接性為外部的,但const全局變量的鏈接性為內(nèi)部的,也就是說,在C++看來,全局const定義就像使用了static說明符一樣


const int fingers =10;  //same as static const int fingers =10;
int main(void)
{
        ...
}

C ++修改了常量類型的規(guī)則,讓程序員更輕松。例如,假設(shè)將一組常量放在頭文件中,并在同一個(gè)程序的多個(gè)文件中使用該頭文件。那么預(yù)處理器將頭文件的內(nèi)容包含到每個(gè)源文件中,所有的源文件都將包含類似下面的定義:


const int finers =10;
const char * warning ="Wak!";

如果全局const聲明的鏈接性像常規(guī)變量那樣是外部的,則根據(jù)單定義規(guī)則,這將出錯(cuò)。也就是說,只能有一個(gè)文件可以包含前面的聲明,而其他文件必須使用extern關(guān)鍵字來提供引用聲明。另外,只有使用extern關(guān)鍵字的聲明才能進(jìn)行初始化:


//extern would be required if ocnst had external linkage
extern const int fingers;  //can't be initialized
extern const char *warning;

因此,需要為某個(gè)文件使用一組定義,而其他文件使用另一組聲明。然而,由于外部定義const數(shù)據(jù)的鏈接性為內(nèi)部的,因此可以在所有文件中使用相同的聲明。

內(nèi)部鏈接性還意味著,每個(gè)文件都有自己的一組常量,而不是所有文件共享一組常量。每個(gè)定義都是其所屬文件私有的,這就是能夠?qū)⒊A慷x放在頭文件中的原因。這樣,只要在兩個(gè)源代碼文件中包括同一個(gè)頭文件,則他們將獲得同一組常量。

如果出于某種原因,程序員希望某個(gè)常量的鏈接性為外部的,則可以使用extern關(guān)鍵字來覆蓋默認(rèn)的內(nèi)部鏈接性。

在函數(shù)或代碼塊中聲明const時(shí),其作用域?yàn)榇a塊,即僅當(dāng)程序執(zhí)行該代碼塊中的代碼時(shí),該常量才是可用的。這意味著在函數(shù)或代碼塊中創(chuàng)建常量時(shí),不必?fù)?dān)心其名稱與其他地方定義的常量發(fā)生沖突。

2.8 函數(shù)和鏈接性

和變量一樣,函數(shù)也有鏈接性,雖然可選擇的范圍比變量小。和C語言一樣,C++不允許在一個(gè)函數(shù)中定義另外一個(gè)函數(shù),因此所有的存儲(chǔ)持續(xù)性都自動(dòng)為靜態(tài)的,即在整個(gè)程序執(zhí)行期間都一直存在。在默認(rèn)情況下,函數(shù)的鏈接性為外部的,即可以在文件間共享。

實(shí)際上,可在函數(shù)原型中使用關(guān)鍵字extern來指出函數(shù)是在另一個(gè)文件中定義的,不過這是可選的(要讓程序在另一個(gè)文件中查找函數(shù),該文件必須作為程序的組成部分被編譯,或者是由鏈接程序搜索的庫(kù)文件)。還可以使用關(guān)鍵字static將函數(shù)的鏈接性設(shè)置為內(nèi)部的,使之只能在一個(gè)文件中使用。必須同時(shí)在原型和函數(shù)定義中使用該關(guān)鍵字。


static int private(double x);
...
static int private(double x)
{
    ...
}

這意味著該函數(shù)只在這個(gè)文件中課件,還意味著可以在其他文件中定義同名的函數(shù)。和變量一樣,在定義靜態(tài)函數(shù)的文件中,靜態(tài)函數(shù)將覆蓋外部定義,因此即使在外部定義了同名的函數(shù),該文件仍將用靜態(tài)函數(shù)。

單定義規(guī)則也適用于非內(nèi)聯(lián)函數(shù),因此對(duì)于每個(gè)非內(nèi)聯(lián)函數(shù),程序只能包含一個(gè)定義,對(duì)于鏈接性為外部的函數(shù)來說,這意味著在多文件程序中,只能有一個(gè)文件(該文件可能是庫(kù)文件,而不是您提供的)包含該函數(shù)的定義,但使用該函數(shù)的每個(gè)文件都應(yīng)包含其函數(shù)原型。

內(nèi)聯(lián)函數(shù)不受這項(xiàng)規(guī)則的約束,這允許程序員能夠?qū)?nèi)聯(lián)函數(shù)的定義放在頭文件中。這樣,包含了頭文件的每個(gè)文件都有內(nèi)聯(lián)函數(shù)的定義。然而,C++要求同一個(gè)函數(shù)的所有內(nèi)聯(lián)定義都必須相同。

2.9 語言鏈接性

另一種形式的鏈接性——稱為語言鏈接性也對(duì)函數(shù)有影響。鏈接程序要求每個(gè)不同的函數(shù)都有不同的符號(hào)名。在C語言中,一個(gè)名稱只對(duì)應(yīng)一個(gè)函數(shù),因此這很容易實(shí)現(xiàn)。為滿足內(nèi)部需求,C語言編譯器可能將spiff這樣的函數(shù)名翻譯為 _spiff。這種方法被稱為C原因鏈接性。但在C++中,同一個(gè)名稱可能對(duì)應(yīng)多個(gè)函數(shù),必須將這些函數(shù)翻譯為不同的符號(hào)名稱。因此,C++編譯器執(zhí)行名稱矯正或名稱修飾,為重載函數(shù)生成不同的符號(hào)名稱。例如,可能將spiff(int)轉(zhuǎn)換為_spoff_i,而將spiff(double, double)轉(zhuǎn)換為_spiff_d_d。這種方法被稱為C++語言鏈接。

鏈接程序?qū)ふ遗cC++函數(shù)調(diào)用匹配的函數(shù)時(shí),使用的方法與C語言不同。但如果要在C++程序中使用C庫(kù)中預(yù)編譯的函數(shù),將出現(xiàn)什么情況呢?例如,假設(shè)有下面的代碼:


spiff(22); //want spiff(int) from a C library

它在C庫(kù)文件中的符號(hào)名稱為_spiff, 但對(duì)于我們假設(shè)的鏈接程序來說,C++查詢約定時(shí)查找符號(hào)名稱 _spiff_i。為解決這種問題,可以用函數(shù)原型來指出要使用的約定:


extern "C" void spiff(int); //use C protocol for name look-up
extern void spoff(int);     //use C++ protocol for name look-up
extern "C++" void spaff(int);  //use C++ protocol for name look-up

第一個(gè)原型使用C語言鏈接性;而后面的兩個(gè)使用C++語言鏈接性。第二個(gè)原型是通過默認(rèn)方式指出這一點(diǎn)的,而第三個(gè)顯式地指出了這一點(diǎn)。

C和C++鏈接性是C++標(biāo)準(zhǔn)制定的說明符,但實(shí)現(xiàn)可提供其他語言鏈接性說明符。

2.10 存儲(chǔ)方案和動(dòng)態(tài)分配

前面介紹C++用來為變量(包括數(shù)組和結(jié)構(gòu))分配內(nèi)存的5種方案(線程內(nèi)存除外),他們不適用于使用C++運(yùn)算符new(或C函數(shù)malloc())分配的內(nèi)存,這種內(nèi)存被稱為動(dòng)態(tài)內(nèi)存。動(dòng)態(tài)內(nèi)存運(yùn)算符由new和delete控制,而不是由作用域和鏈接性規(guī)則控制。因此,可以在一個(gè)函數(shù)中分配動(dòng)態(tài)內(nèi)存,而在另一個(gè)函數(shù)中將其釋放。與自動(dòng)內(nèi)存不同,動(dòng)態(tài)內(nèi)存不是LIFO,其分配和釋放順序要取決于new和delete在何時(shí)以何種方式被使用。通常,編譯器使用三塊獨(dú)立的內(nèi)存:一塊用于靜態(tài)變量,一塊用于自動(dòng)變量,另外一塊用于動(dòng)態(tài)存儲(chǔ)。

雖然存儲(chǔ)方案概念不適用于動(dòng)態(tài)內(nèi)存,但適用于用來跟蹤動(dòng)態(tài)內(nèi)存的自動(dòng)和靜態(tài)指針變量。例如,假設(shè)在一個(gè)函數(shù)中包含下面的語句:


float * p_free =new float [20];

由new分配的80個(gè)字節(jié)(假設(shè)float為4個(gè)字節(jié))的內(nèi)存將一直保留在內(nèi)存中,直到使用delete運(yùn)算符將其釋放。但當(dāng)包含該聲明語句塊執(zhí)行完畢時(shí),p_fees指針將消失。如果希望另一個(gè)函數(shù)能夠使用這80個(gè)字節(jié)的內(nèi)存,則必須將其地址傳遞或返回給該函數(shù)。另一方面,如果將p_fees的鏈接性聲明為外部的,則文件中位于該聲明后面的所有函數(shù)都可以使用它。另外,通過在另一個(gè)文件中使用下述聲明,便可在其中使用該指針:


extern float * p_fees;

1. 使用new運(yùn)算符初始化

如果要初始化動(dòng)態(tài)分配的變量,該如何辦呢?在C++98中,有時(shí)候可以這樣做,C++11增加了其他可能性。

如果要為內(nèi)置的標(biāo)量類型(如int或double)分配存儲(chǔ)空間并初始化,可在類型名后面加上初始值,并將其用括號(hào)括起:


int *pi =new int(6); 
double * pd =new double (99.99);

這種括號(hào)語法也有可用于構(gòu)造函數(shù)的類,這將在本書后面介紹。

然而,要初始化常規(guī)結(jié)構(gòu)或數(shù)組,需要使用大括號(hào)的列表初始化,這要求編譯器支持C++11。C++11允許您這樣做:


struct where {double x; double y; double z;};
where * one =new where {2.5, 5.3, 7.2}; //C++11
int * ar =new int [4] {2,4,6,7}; //C++11

在C++11中,還可將列表初始化用于單值變量:


int *pin =new int {};
double *pdo= new double {99.99};

2. new 失敗時(shí)

new可能找不到請(qǐng)求的內(nèi)存量。在最初10年中,C++在這種情況下讓new返回空指針,但現(xiàn)在將引發(fā)一場(chǎng)std::bad_alloc。

3. new: 運(yùn)算符、函數(shù)和替換函數(shù)

運(yùn)算符new和new[]分別調(diào)用如下函數(shù):


void * operator new(std::size_t); //used by new
void * operator new[] (std:: size_t) //used by new[]

這些函數(shù)被稱為分配函數(shù),他們位于全局名稱空間中。同樣也有delete和delete[]調(diào)用的釋放函數(shù):


void operator delete(void *);
void operator delete [](void *);

4. 定位new運(yùn)算符

通常,new負(fù)責(zé)在堆中找到一個(gè)足以能夠滿足要求的內(nèi)存塊。new運(yùn)算符還有另一種變體,被稱為定位new運(yùn)算符,它讓您能夠指定要使用的位置。程序員可能使用這種特性來設(shè)置其內(nèi)存管理規(guī)程、處理需要通過特定地址進(jìn)行訪問的硬件或在特定位置創(chuàng)建對(duì)象。

要使用定位new特性,首先需要包含頭文件new,它提供了這種版本的new運(yùn)算符的原型;然后將new運(yùn)算符用于提供了所需地址的參數(shù)。除需要指定參數(shù)外,句法與常規(guī)new運(yùn)算符相同。具體地說,使用定位new運(yùn)算符,變量后面可以有方括號(hào),也可以沒有。下面演示了new運(yùn)算符的4種用法:


#include <new>
struct chaff
{
	char dross[20];
	int slag;
 } ;
 char buffer1[50];
 int *p3, *p4;
 //first, the regular forms of new
 p1 = new chaff;    //place structure in heap
 p3 = new int [20]; // place int array in heap
 //now, the two forms of placement new
 p2 = new (buffer1) chaff;   //place structure in buffer1
 p4 = new (buffer2) int[20]; //place int array in buffer2
 ...

出于簡(jiǎn)化的目的,這個(gè)示例使用兩個(gè)靜態(tài)數(shù)組來為定位new運(yùn)算符提供內(nèi)存空間。因此,上述代碼從buffer1中分配空間給結(jié)構(gòu)chaff, 從buffer2中分配空間給一個(gè)包含20個(gè)元素的int數(shù)組。

3. 名稱空間

C++中,名稱可以是變量、函數(shù)、結(jié)構(gòu)、枚舉。類以及類和結(jié)構(gòu)的成員。當(dāng)隨著項(xiàng)目的增大,名稱相互沖突的可能性也將增加。使用多個(gè)廠商的類庫(kù)時(shí),可能導(dǎo)致名稱沖突。例如,兩個(gè)庫(kù)可能都定義了名稱為L(zhǎng)ist、Tree和Node的類,但定義的方式不兼容。用戶可能希望使用一個(gè)庫(kù)的List類,而使用另一個(gè)庫(kù)的Tree類。這種沖突被稱為名稱空間問題。

C++標(biāo)準(zhǔn)提供了名稱空間工具,以便更好地控制名稱的作用域。經(jīng)過了一段時(shí)間后,編譯器才支持名稱空間,但現(xiàn)在這種支持很普遍。

3.1 傳統(tǒng)的C++名稱空間

介紹C++中新增的名稱空間特性之前,先復(fù)習(xí)一下C++中已有的名稱空間屬性,以及概念。

聲明區(qū)域。聲明區(qū)域是可以在其中進(jìn)行聲明的區(qū)域。例如,可以在函數(shù)外面聲明全局變量,對(duì)于這種變量,其聲明區(qū)域?yàn)槠渌诘奈募?。?duì)于在函數(shù)中聲明的變量,其聲明區(qū)域?yàn)槠渎暶魉诘拇a塊。

潛在作用域。變量的潛在作用域從聲明點(diǎn)開始,到其聲明區(qū)域的結(jié)尾。因此潛在作用域比聲明區(qū)域小,這是由于變量必須定義后才能使用。

然而,變量并非在其潛在作用域內(nèi)的任何位置都是可見的。例如,它可能被另一個(gè)嵌套聲明區(qū)域中聲明的同名變量隱藏。例如,在函數(shù)中聲明的局部變量將隱藏在同一個(gè)文件中聲明的全局變量。變量對(duì)程序而言可見的范圍被稱為作用域。

C++關(guān)于全局變量和局部變量的規(guī)則定義了一種名稱空間層次。每個(gè)聲明區(qū)域都可以聲明名稱,這些名稱獨(dú)立于在其他聲明區(qū)域中聲明的名稱。在一個(gè)函數(shù)中聲明的局部變量不會(huì)與在另一個(gè)函數(shù)中聲明的局部變量發(fā)生沖突。

3.2 新的名稱空間特性

C++新增了這樣一種功能,即通過定義一種新的聲明區(qū)域來創(chuàng)建命名的名稱空間,這樣做得目的之一是提供一個(gè)聲明名稱的區(qū)域。一個(gè)名稱空間中的名稱不會(huì)與另外一個(gè)名稱空間的相同名稱發(fā)生沖突,同時(shí)允許程序的其他部分使用該名稱空間中聲明的東西。

名稱空間可以是全局的,也可以位于另一個(gè)名稱空間中,但不能位于代碼塊中。因此,在默認(rèn)情況下,在名稱空間中聲明的名稱的鏈接性為外部的。

除了用戶定義的名稱空間外,還存在另一個(gè)名稱空間——全局名稱空間。它對(duì)應(yīng)于文件級(jí)聲明區(qū)域,因此前面所說的全局變量現(xiàn)在被描述為位于全局名稱空間中。

任何名稱空間中的名稱都不會(huì)與其他名稱空間中的名稱發(fā)生沖突。名稱空間中的聲明和定義規(guī)則同全局聲明和定義規(guī)則相同。

名稱空間是開放的,即可以把名稱空間加入到已有的名稱空間中。下面這條語句將名稱goose添加到Jill中已有的名稱列表中:


namespace Jill {
    char * goose(const char *);
}

同樣,原來的Jack名稱空間為fetch()函數(shù)提供了原型??梢栽谠撐募竺妫ɑ蛄硗庖粋€(gè)文件中)再次使用Jack名稱空間來提供該函數(shù)的代碼:


namespace Jack{
    void fetch()
    {
        ...
    }
}

當(dāng)然,需要有一種方法來訪問給定名稱空間中的名稱。最簡(jiǎn)單的方法是,通過作用域解析運(yùn)算符::,使用名稱空間來限定該名稱:


Jack:: pail =12.34; //use a variable
Jill::Hill mole;    //create a type Hill structure
Jack::fetch();      //use a function

未被裝飾的名稱稱為未限定的名稱;包含名稱空間的名稱稱為限定的名稱。

1. using聲明和using編譯指令

C++提供兩種機(jī)制(using聲明和using編譯指令)來簡(jiǎn)化對(duì)名稱空間中名稱的使用。using聲明使特定的標(biāo)識(shí)符可用,using編譯指令使整個(gè)名稱空間可用。

using聲明由被限定的名稱和它前面的關(guān)鍵字using組成,using聲明將特定的名稱添加到它所屬的聲明區(qū)域中。

using聲明使一個(gè)名稱可用,而using編譯指令使所有的名稱都可用。using編譯指令由名稱空間名和它前面的關(guān)鍵字using namespace組成,它使名稱空間中的所有名稱都可用,而不需要使用作用域解析運(yùn)算符。

在全局聲明區(qū)域中使用using編譯指令,將使該名稱空間的名稱全局可用。在函數(shù)中使用using 編譯指令,將使其中的名稱在該函數(shù)中可用。

2. using編譯指令和using聲明之比較

使用using編譯指令導(dǎo)入一個(gè)名稱空間中所有的名稱與使用多個(gè)using聲明使不一樣的,而更像是大量使用作用域解析運(yùn)算符。使用using聲明時(shí),就好像聲明了相應(yīng)的名稱一樣。如果某個(gè)名稱已經(jīng)在函數(shù)中聲明了,則不能用using聲明導(dǎo)入相同的名稱。然而,使用using編譯指令時(shí),將進(jìn)行名稱解析,就像在包含using聲明和名稱空間本身的最小聲明區(qū)域中聲明了名稱一樣。

注意:假設(shè)名稱空間和聲明區(qū)域定義了相同的名稱。如果試圖使用using聲明將名稱空間的名稱導(dǎo)入該聲明區(qū)域,則這兩個(gè)名稱會(huì)發(fā)生沖突,從而出錯(cuò)。如果使用using編譯指令將該名稱空間的名稱導(dǎo)入該聲明區(qū)域,則局部版本將隱層名稱空間版本。

一般來說,使用using聲明比使用using編譯指令更安全,這是由于它只導(dǎo)入指定的名稱。如果該名稱與局部名稱發(fā)生沖突,編譯器將發(fā)出指示。using編譯指令導(dǎo)入所有名稱,包括可能并不需要的名稱。如果與局部名稱發(fā)生沖突,則局部名稱將覆蓋名稱空間版本,而編譯器并不會(huì)發(fā)出警告。另外,名稱空間的開放性意味著名稱空間的名稱可能分散在多個(gè)地方,這使得難以準(zhǔn)確知道添加了哪些名稱。

3. 名稱空間的其他特性

可以將名稱空間聲明進(jìn)行嵌套:


namespace elements
{
    namespace fire
    {
        int flame;
        ...
    }
    float water;
}

4. 未命名的名稱空間

可以通過省略名稱空間的名稱來創(chuàng)建未命名的名稱空間


namespace  //unnamed namespace
{
    int ice;
    int bandycoot;
}

這就像后面跟著using編譯指令一樣,也就是說,在該名稱空間中聲明的名稱潛在作用域?yàn)椋簭穆暶鼽c(diǎn)到該聲明區(qū)域末尾。從這個(gè)方面看,它們與全局變量相似。然而,由于這種名稱空間沒有名稱,因此不能顯式地使用using編譯指令或using聲明來使它在其他位置都可用。具體的說,不能在未命名名稱空間所屬文件之外的其他文件中,使用該名稱空間中的名稱。這提供了鏈接性為內(nèi)部的靜態(tài)變量的替代品。

3.3 名稱空間及其前途

隨著程序員逐漸熟悉名稱空間,將出現(xiàn)統(tǒng)一的編程理念。下面是當(dāng)前的一些指導(dǎo)原則。

  • 使用在已命名的名稱空間中聲明的變量,而不是使用外部全局變量。
  • 使用在已命名的名稱空間中聲明的變量,而不是使用靜態(tài)全局變量。
  • 如果開發(fā)了一個(gè)函數(shù)庫(kù)或類庫(kù),將其放在一個(gè)名稱空間中。事實(shí)上,C++當(dāng)前提倡將標(biāo)準(zhǔn)函數(shù)庫(kù)放在名稱空間std中,這種做法擴(kuò)展到了來自C語言中的函數(shù)。例如,頭文件math.h是與C語言兼容的,沒有使用名稱空間,但C++頭文件cmath應(yīng)將各種數(shù)學(xué)庫(kù)函數(shù)放在名稱空間std中。實(shí)際上,并非所有的編譯器都完成了這種過渡。
  • 僅將編譯指令using作為一種將舊代碼轉(zhuǎn)換為使用名稱空間的權(quán)宜之計(jì)。
  • 不要在頭文件中使用using編譯指令。首先,這樣做掩蓋了要讓哪些名稱可用;另外,包含頭文件的順序可能影響程序的行為。如果非要使用編譯指令using,應(yīng)將其放在所有預(yù)處理器編譯指令#include之后。
  • 導(dǎo)入名稱時(shí),首選使用作用域解析運(yùn)算符或using聲明的方法。
  • 對(duì)于using聲明,首選將其作用域設(shè)置為局部而不是全局。

使用名稱空間的主旨是簡(jiǎn)化大型編程項(xiàng)目的管理工作。對(duì)于只有一個(gè)文件的簡(jiǎn)單程序,使用using編譯指令并非什么大逆不道的事。

4 .總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注html5模板網(wǎng)的更多內(nèi)容!

【網(wǎng)站聲明】本站部分內(nèi)容來源于互聯(lián)網(wǎng),旨在幫助大家更快的解決問題,如果有圖片或者內(nèi)容侵犯了您的權(quán)益,請(qǐng)聯(lián)系我們刪除處理,感謝您的支持!

相關(guān)文檔推薦

主站蜘蛛池模板: 红立方品牌应急包/急救包加盟,小成本好项目代理_应急/消防/户外用品加盟_应急好项目加盟_新奇特项目招商 - 中红方宁(北京) 供应链有限公司 | 安徽千住锡膏_安徽阿尔法锡膏锡条_安徽唯特偶锡膏_卡夫特胶水-芜湖荣亮电子科技有限公司 | 阁楼货架_阁楼平台_仓库仓储设备_重型货架_广州金铁牛货架厂 | 深圳标识制作公司-标识标牌厂家-深圳广告标识制作-玟璟广告-深圳市玟璟广告有限公司 | 北京乾茂兴业科技发展有限公司 | 微信聊天记录恢复_手机短信删除怎么恢复_通讯录恢复软件下载-快易数据恢复 | 吸音板,隔音板,吸音材料,吸音板价格,声学材料 - 佛山诺声吸音板厂家 | 信阳网站建设专家-信阳时代网联-【信阳网站建设百度推广优质服务提供商】信阳网站建设|信阳网络公司|信阳网络营销推广 | 合肥地磅_合肥数控切割机_安徽地磅厂家_合肥世佳电工设备有限公司 | 鄂泉泵业官网|(杭州、上海、全国畅销)大流量防汛排涝泵-LW立式排污泵 | 数控车床-立式加工中心-多功能机床-小型车床-山东临沂金星机床有限公司 | 爱科技iMobile-专业的科技资讯信息分享网站 | 碳纤维复合材料制品生产定制工厂订制厂家-凯夫拉凯芙拉碳纤维手机壳套-碳纤维雪茄盒外壳套-深圳市润大世纪新材料科技有限公司 | 胶泥瓷砖胶,轻质粉刷石膏,嵌缝石膏厂家,腻子粉批发,永康家德兴,永康市家德兴建材厂 | 丹佛斯变频器-丹佛斯压力开关-变送器-广州市风华机电设备有限公司 | 粘弹体防腐胶带,聚丙烯防腐胶带-全民塑胶 | 达利园物流科技集团-| 大型多片锯,圆木多片锯,方木多片锯,板材多片锯-祥富机械有限公司 | 小型铜米机-干式铜米机-杂线全自动铜米机-河南鑫世昌机械制造有限公司 | 新疆系统集成_新疆系统集成公司_系统集成项目-新疆利成科技 | 膜结构_ETFE膜结构_膜结构厂家_膜结构设计-深圳市烨兴智能空间技术有限公司 | 河南膏药贴牌-膏药代加工-膏药oem厂家-洛阳今世康医药科技有限公司 | IWIS链条代理-ALPS耦合透镜-硅烷预处理剂-上海顶楚电子有限公司 lcd条形屏-液晶长条屏-户外广告屏-条形智能显示屏-深圳市条形智能电子有限公司 | 压力控制器,差压控制器,温度控制器,防爆压力控制器,防爆温度控制器,防爆差压控制器-常州天利智能控制股份有限公司 | 耐磨陶瓷管道_除渣器厂家-淄博浩瀚陶瓷科技有限公司 | 山东集装箱活动房|济南集装箱活动房-济南利森集装箱有限公司 | 石膏基自流平砂浆厂家-高强石膏基保温隔声自流平-轻质抹灰石膏粉砂浆批发-永康市汇利建设有限公司 | 进口消泡剂-道康宁消泡剂-陶氏消泡剂-大洋消泡剂 | 针焰试验仪,灼热丝试验仪,漏电起痕试验仪,水平垂直燃烧试验仪 - 苏州亚诺天下仪器有限公司 | 防水接头-电缆防水接头-金属-电缆密封接头-不锈钢电缆接头 | 深圳高新投三江工业消防解决方案提供厂家_服务商_园区智慧消防_储能消防解决方案服务商_高新投三江 | 渣油泵,KCB齿轮泵,不锈钢齿轮泵,重油泵,煤焦油泵,泊头市泰邦泵阀制造有限公司 | 测试治具|过炉治具|过锡炉治具|工装夹具|测试夹具|允睿自动化设备 | 防爆型气象站_农业气象站_校园气象站_农业四情监测系统「山东万象环境科技有限公司」 | 上海盐水喷雾试验机_两厢式冷热冲击试验箱-巨怡环试 | 模切之家-专注服务模切行业的B2B平台!| 背压阀|减压器|不锈钢减压器|减压阀|卫生级背压阀|单向阀|背压阀厂家-上海沃原自控阀门有限公司 本安接线盒-本安电路用接线盒-本安分线盒-矿用电话接线盒-JHH生产厂家-宁波龙亿电子科技有限公司 | 胜为光纤光缆_光纤跳线_单模尾纤_光纤收发器_ODF光纤配线架厂家直销_北京睿创胜为科技有限公司 - 北京睿创胜为科技有限公司 | 铁素体测量仪/检测仪/铁素体含量测试仪-苏州圣光仪器有限公司 | 复合土工膜厂家|hdpe防渗土工膜|复合防渗土工布|玻璃纤维|双向塑料土工格栅-安徽路建新材料有限公司 | 超声波气象站_防爆气象站_空气质量监测站_负氧离子检测仪-风途物联网 |