1. 程式人生 > 其它 >C++中的持續性和連結性

C++中的持續性和連結性

一.靜態持續性,外部連結性

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的配套使用。