C++中extern的使用
在C++中,extern主要有兩個作用:(1)、extern聲明一個變量或函數;(2)、extern與”C”一起連用,用于鏈接指定。關于extern “C”的使用可以參考:?http://blog.csdn.net/fengbingchun/article/details/78634831 ,這里主要介紹extern聲明一個變量或函數時的用法。
extern可置于變量或者函數前,以表示變量或者函數的定義在別的文件中,提示編譯器遇到此變量或函數時,在其它模塊中尋找其定義。
如果想聲明一個變量而非定義它,就在變量名稱前加關鍵字extern,而且不要顯示地初始化變量。任何包含了顯示初始化的聲明即成為定義。我們能給由extern關鍵字標記的變量賦一個初始值,但是這么做也就抵消了extern的作用。extern語句如果包含初始值就不再是聲明,而變成定義了。在函數體內部,如果試圖初始化一個由extern關鍵字標記的變量,將引發錯誤。變量能且只能被定義一次,但是可以被多次聲明。聲明和定義的區別看起來也許微不足道,但實際上卻非常重要。如果要在多個文件中使用同一個變量,就必須將聲明和定義分離。此時,變量的定義必須出現在且只能出現在一個文件中,而其它用到該變量的文件必須對其進行聲明,卻絕對不能重復定義。
某些時候有這樣一種const變量,它的初始值不是一個常量表達式,但又確實有必要在文件間共享。這種情況下,我們不希望編譯器為每個文件分別生成獨立的變量。相反,我們想讓這類const對象像其它(非常量)對象一樣工作,也就是說,只在一個文件中定義const,而在其它多個文件中聲明并使用它。解決的辦法是,對于const變量不管是聲明還是定義都添加extern關鍵字,這樣只需定義一次就可以了。如果想在多個文件之間共享const對象,必須在變量的定義之前添加extern關鍵字。
在大系統中,在多個文件中實例化相同模板的額外開銷可能非常嚴重。在新標準中,我們可以通過顯示實例化(explicit instantiation)來避免這種開銷。一個顯示實例化有如下形式:
extern template declaration; // 實例化聲明
template declaration; // 實例化定義
 declaration是一個類或函數聲明,其中所有模板參數已被替換為模板實參。
當編譯器遇到extern模板聲明時,它不會在本文件中生成實例化代碼。將一個實例化聲明為extern就表示承諾在程序其它位置有該實例化的一個非extern聲明(定義)。對于一個給定的實例化版本,可能有多個extern聲明,但必須只有一個定義。由于編譯器在使用一個模板時自動對其實例化,因此extern聲明必須出現在任何使用此實例化版本的代碼之前。當編譯器遇到一個實例化定義(與聲明相對)時,它為其生成代碼。
對每個實例化聲明,在程序中某個位置必須有其顯示的實例化定義。一個類模板的實例化定義會實例化該模板的所有成員,包括內聯的成員函數。當編譯器遇到一個實例化定義時,它不了解程序使用哪些成員函數。因此,與處理類模板的普通實例化不同,編譯器會實例化該類的所有成員。即使我們不使用某個成員,它也會被實例化。因此,我們用來顯示實例化一個類模板的類型,必須能用于模板的所有成員。
在一個類模板的實例化定義中,所用類型必須能用于模板的所有成員函數。
模板顯示實例化(explicit instantiation):一個聲明,為所有模板參數提供了顯示實參。用來指導實例化過程。如果聲明是extern的,模板將不會被實例化;否則,模板將利用指定的實參進行實例化。對每個extern模板聲明,在程序中某處必須有一個非extern的顯示實例化。
關鍵字extern為聲明但不定義一個對象提供了一種方法,實際上它類似于函數聲明,承諾了該對象會在其它地方被定義或者在此文本文件中的其它地方,或者在程序的其它文本文件中。extern聲明不會引起內存被分配,它可以在同一文件中或同一程序的不同文件中出現多次。關鍵字extern也可以在函數聲明中指定,唯一的影響是將該聲明為隱式屬性,在其它地方定義,變為顯示的。extern關鍵字告訴編譯器,”這個變量可能定義在這個模塊或其它模塊中”,一個extern聲明并沒有生成數據,它僅表明這個數據是共享的。這個變量必須是在別處定義過的,而且它只能定義一次。
以下是測試代碼:
extern.hpp:
#ifndef FBC_CPPBASE_TEST_EXTERN_HPP_
#define FBC_CPPBASE_TEST_EXTERN_HPP_namespace extern_ {extern const int bufsize; // 與.cpp中定義的bufsize是同一個int test_extern_1();
int test_extern_2();} // namespace extern_#endif // FBC_CPPBASE_TEST_EXTERN_HPP_
 extern.cpp:
#include "extern.hpp"
#include <iostream>extern std::string extern_variable_blog_addr;
extern std::string extern_variable_github_addr;
extern int extern_function_add(int a, int b);
extern const std::string extern_function_name();namespace extern_ {namespace {int fcn() { return 0; }
}extern double pi = 3.1415; // 定義/* reference: C++ Primer(Fifth 中文版) pages 63
某些時候有這樣一種const變量,它的初始值不是一個常量表達式,但又確實有必要在文件間共享。
這種情況下,我們不希望編譯器為每個文件分別生成獨立的變量。相反,我們想讓這類const對象
像其它(非常量)對象一樣工作,也就是說,只在一個文件中定義const,而在其它多個文件中聲明
并使用它。解決的辦法是,對于const變量不管是聲明還是定義都添加extern關鍵字,這樣只需定義一次就可以了
*/
extern const int bufsize = fcn();int test_extern_1()
{extern int i; // 聲明i而非定義iint j; // 聲明并定義j//extern double pi = 3.1415; // 定義,在函數體內部,如果試圖初始化一個由extern關鍵字標記的變量,將引發錯誤return 0;
}int test_extern_2()
{fprintf(stdout, "blob addr: %s\n", extern_variable_blog_addr.c_str());fprintf(stdout, "github addr: %s\n", extern_variable_github_addr.c_str());fprintf(stdout, "a + b = %d\n", extern_function_add(2, 3));fprintf(stdout, "name: %s\n", extern_function_name().c_str());return 0;
}} // namespace extern_
 extern2.hpp:
#ifndef FBC_CPPBASE_TEST_EXTERN2_HPP_
#define FBC_CPPBASE_TEST_EXTERN2_HPP_#include <string>extern std::string extern_variable_blog_addr;
extern std::string extern_variable_github_addr;
extern int extern_function_add(int a, int b);
extern const std::string extern_function_name();#endif // FBC_CPPBASE_TEST_EXTERN2_HPP_
 extern2.cpp:
#include "extern2.hpp"std::string extern_variable_blog_addr{ "http://blog.csdn.net/fengbingchun" };
std::string extern_variable_github_addr{ "https://github.com/fengbingchun" };int extern_function_add(int a, int b)
{return (a + b);
}extern const std::string extern_function_name()
{return "C++";
}
GitHub:? https://github.com/fengbingchun/Messy_Test?
總結
以上是生活随笔為你收集整理的C++中extern的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: Linux下__attribute__(
 - 下一篇: 主成分分析(PCA)简介