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而非定義i
int 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/C++中extern關鍵字詳解C++
- extern "C"的用途—在C++程式碼中嵌入C程式碼C++C程式
- C++中extern “C”含義深層探索 (轉載)C++
- c++基礎知識(八)C/C++中修飾符const、extern、static、volatile的用法C++
- 在c++程式中呼叫被C編譯器編譯後的函式,為什麼要使用extern “C”C++編譯函式
- iOS之const,static,extern使用iOS
- iOS中的static const extern關鍵字iOS
- extern "c"的用法
- extern "C"的用法解析
- C++中std::allocator的使用C++
- 嵌入式開發程式碼中的extern "C" {的作用
- C中的auto、static、register、extern、const和volitate
- extern c 解析
- C++ 中各種map的使用C++
- C語言中extern的用法C語言
- static 和extern的區別
- c語言extern的用法C語言
- extern、 const、static的理解
- extern用法詳解
- extern "c" 用法解析
- extern "C" __declspec(dllexport)Export
- extern作用詳解
- C++中compare函式的使用C++函式
- c++ builder中的ado使用 (轉)C++UI
- extern int a 和int a的區別
- C++關鍵字(static/register/atuo/extern/volatile/const)釋疑 (轉)C++
- C++中map的使用詳解說明C++
- C++中過載new和delete的使用C++delete
- C與C++中struct使用的區別C++Struct
- c++中new和delete的使用方法C++delete
- C語言:extern用法C語言
- C語言extern用法C語言
- C++共享之道:用extern實現原始檔變數與類成員函式的巧妙共享C++變數函式
- 關於在VC++中使用 extern C遇到的stdafx.h的問題C++
- 使用c++中string類的注意事項C++
- const,static,extern簡介
- c++中getopt和getopt_long的使用方法C++
- C++中簡單使用HP-SocketC++