C++中的持續性和連結性
阿新 • • 發佈:2022-03-02
一.靜態持續性,外部連結性
1.單定義規則
定義宣告:分配儲存空間
引用宣告:不分配儲存空間,使用關鍵字extern;
//file01.cpp extern int cats=20; int dogs=22; int fleas; //file02.cpp extern int cats; extern int dogs; //file98.cpp extern int dogs; extern int cats; extern int fleas;
二。靜態持續性,內部連線性
在加上關鍵字static後,該變數為內部連結性,在其它檔案中定義不會衝突。
若在兩個檔案中使用一個變數名,則會報錯。
三,靜態持續性,無連結性
const int ArSize = 10; void strcount(const char* str); int main() { char input[ArSize]; char next; cout << "Enter a line\n"; cin.get(input, ArSize); while (cin) //cin.get(char*,int)讀取空行會導致false { cin.get(next); while (next != '\n') { cin.get(next); } strcount(input); cout << "Enter next line (empty line to quit):\n"; cin.get(input, ArSize); } } void strcount(const char* str) { static int total = 0; int count = 0; cout << "\"" << str << "\" contains"; while (*str++) { count++; } total += count; cout << count << " characters \n"; cout << total << " characters total\n"; }
程式碼執行結果:
Enter a line nice pants "nice pant" contains9 characters 9 characters total Enter next line (empty line to quit): thanks "thanks" contains6 characters 15 characters total Enter next line (empty line to quit): parting is such sweet sorrow "parting i" contains9 characters 24 characters total Enter next line (empty line to quit): ok "ok" contains2 characters 26 characters total Enter next line (empty line to quit):
count被重置,而total不會
總的來說,當static被用於全域性時,表現為內部連結性,用於區域性時,表現為儲存持續性。
四.const
const全域性變數連結性是內部的,這樣使得在標頭檔案中定義的const可以在多個原始檔中可用,而不會出現重複定義的報錯,並且內部連結性以為著該變數是檔案私有的,不會被多個檔案間共享。
如果此時希望const修飾的變數的連結性是外部的,可以用extern來覆蓋內部連結性。
五。函式和連結性
預設情況下,函式的連結性是外部的,儲存性是靜態的,可以在檔案之間共享,使用extern引用宣告,不過這是可選的。
也可以使用static使其只能在一個檔案內使用,並且會覆蓋外部定義。
行內函數不受這種約束,允許將行內函數的定義放在標頭檔案中。
C++將在哪裡去查詢函式?
如果原型指出該函式是靜態的,則只在該檔案中查詢,否則編譯器將在其他檔案中查詢,若找不到,會到庫檔案中查詢,編譯器會優先選擇自己定義的版本。
六。儲存方案和動態分配
1.使用new初始化
int *pi =new int(6); double *pd= new double (99.99); struct where{double x; double y; double z;}; where * one = new where {2.5,5.3,7.2}; //c++11 inbt *ar = new int[4] {2,4,6,8}; //c++11 //在c++11中,可以用列表初始化單值變數 int *pin =new int {}; double *pdo = new double{99.99};
2.當new初始化失敗時,早期時返回空指標,當現在返回異常std::bad_alloc.
3.new:運算子,函式和替換函式
//函式原型 void *operator new(std::size_t); void *operator[] new(std::size_t); void delete new(void*); void delete[] new(void*); //使用時 int * pi=new int; //int * pi=new(sizeof(int)); int *pa =new int[40]; // int *pa=new(40*sizeof(int)); delete pi;//delete(pi);
4.定位new運算子
#include<new> using namespace std; struct chaff { char dross[20]; int slag; }; char buffer1[50]; char buffer2[500]; int main() { chaff* p1, *p2; int* p3, * p4; //the normal means p1 = new chaff; p3 = new int[20]; //the placement means p2 = new(buffer1) chaff; p4 = new(buffer2) int[20]; }
#include<iostream> #include<new> using namespace std; const int BUF = 512; const int N = 5; char buf[BUF]; int main() { double* pd1, * pd2; pd1 = new double[N]; pd2 = new (buf) double[N]; cout << "Calling new and placement new first:" << endl; for (int i = 0; i < N; i++) { pd1[i] = pd2[i] = 1000 + 20.0 * i; } cout << "Memory address:\n" << "heap:" << pd1 << "static:" << (void*)buf << endl; for (int i = 0; i < N; i++) { cout << pd1[i] << " at " << &pd1[i] << endl; cout << pd2[i] << " at " << &pd2[i] << endl; } cout << "Calling new and placement new a second time" << endl; double* pd3, * pd4; pd3 = new double[N]; pd4 = new (buf) double[N]; for (int i = 0; i < N; i++) { pd3[i] = pd4[i] = 1000 + 40.0 * i; } cout << "Memory comments: " << endl; for (int i = 0; i < N; i++) { cout << pd3[i] << " at " << &pd3[i] << endl; cout << pd4[i] << " at " << &pd4[i] << endl; } cout << "Calling new and placement new a third time" << endl; delete[] pd1; pd1 = new double[N]; pd2 = new (buf+N*sizeof(double)) double[N]; for (int i = 0; i < N; i++) { pd2[i] = pd1[i] = 1000 +60.0 * i; } cout << "Memory comments: " << endl; for (int i = 0; i < N; i++) { cout << pd1[i] << " at " << &pd1[i] << endl; cout << pd2[i] << " at " << &pd2[i] << endl; } }
執行結果:
Calling new and placement new first: Memory address: heap:000001E0566396F0static:00007FF6910E06D0 1000 at 000001E0566396F0 1000 at 00007FF6910E06D0 1020 at 000001E0566396F8 1020 at 00007FF6910E06D8 1040 at 000001E056639700 1040 at 00007FF6910E06E0 1060 at 000001E056639708 1060 at 00007FF6910E06E8 1080 at 000001E056639710 1080 at 00007FF6910E06F0 Calling new and placement new a second time Memory comments: 1000 at 000001E056643C40 1000 at 00007FF6910E06D0 1040 at 000001E056643C48 1040 at 00007FF6910E06D8 1080 at 000001E056643C50 1080 at 00007FF6910E06E0 1120 at 000001E056643C58 1120 at 00007FF6910E06E8 1160 at 000001E056643C60 1160 at 00007FF6910E06F0 Calling new and placement new a third time Memory comments: 1000 at 000001E056643700 1000 at 00007FF6910E06F8 1060 at 000001E056643708 1060 at 00007FF6910E0700 1120 at 000001E056643710 1120 at 00007FF6910E0708 1180 at 000001E056643718 1180 at 00007FF6910E0710 1240 at 000001E056643720 1240 at 00007FF6910E0718
其中buf不可以使用delete釋放,buffer在delete的管轄區之外,這進一步驗證了new和delete的配套使用。