《C 覆轍錄》 1 3 全域性變數

2021-09-23 16:43:53 字數 1711 閱讀 5848

很難找到任何理由去硬生生地宣告什麼全域性變數。全域性變數阻礙了**重用,而且使**變得更難維護。它們阻礙重用是因為任何使用了全域性變數的**就立刻與之耦合,這使得全域性變數一改它們也非得跟著改,從而使任何重用都不可能了。它們使**變得更難維護的原因是很難甄別出哪些**用了某個特定的全域性變數,因為任何**都有訪問它們的許可權。

全域性變數增加了模組間的耦合,因為它們往往作為幼稚的模組間訊息傳遞機制的設施存在。就算它們能擔此重任,從實踐角度來說8,要從大型軟體的源**中去掉任何全域性變數都幾乎不可能9。這還是說他們能正常工作的情況。不過可不要忘了,全域性變數是不設防的。隨便哪個維護你**的c++ 新手都能讓你對全域性變數有強烈依賴的軟體所玩的把戲隨時坍臺。

全域性變數的辯護者們經常拿它的「方便」來說事。這真是自私自利之徒的無恥之爭。要知道,軟體的維護常常比它的初次開發要花費更多時間,而使用全域性變數就意味著把爛攤子扔給了維護工程師。假設我們有乙個系統,它有乙個全域性可訪問的「環境」,並且我們按需求保證確實只有「乙個」。不幸的是,我們選擇了使用全域性變數來表示它:

`extern environment * const theenv; `

我們的需求一時如此,但馬上就行不通了。在軟體就要交付之前,我們會發現,可能同時存在的環境要增加到兩個、三個或是在系統啟動時指定的或根本就是完全動態的某個數。這種在軟體發布的最後時刻發生的變更實屬家常便飯。在備有無微不至的源**控制過程的大專案裡,這個變更會引發極費時間、涉及所有原始檔的更改,即使在最細小的和最直截了當的那些地方也不例外。整個過程預計要幾天到幾星期不等。假如我們不用全域性變數這個災星,只要5分鐘我們就能搞定這一切:

`environment *theenv();`

僅僅是把對於值的訪問加了函式的包裝,我們就獲得了可貴的可擴充性。要是再加上函式過載,或是給予函式形參以預設值,我們就根本不要怎麼改源**了:

`environment *theenv( envcode whichenv = official );`

另乙個全域性變數引起的問題並不能一望即知。此問題的**是全域性變數經常要求延遲到執行期才進行的靜態初始化。c++語言裡如果靜態變數用來初始化的值不能在編譯期就計算妥當,那麼這個初始化的動作就會被拖到執行期。這是許多致命後果的始作俑者(此問題非常重要,常見錯誤55專門來討論此問題):

extern environment * const theenv = new officialenv;  ```

如果改用函式或class來充當訪問全域性資訊的掮客,初始化動作就會被延後,從而也就變得安全無虞了:

class environment ;`

// ...

environment *environment::instance_ = 0;

environment &environment::instance() ```

在上述例子中,我們採用了稱為單件設計模式(`singleton pattern`)的乙個簡單實現10,以所謂「緩式求值」形式完成靜態指標的初始化動作(如果一定要在技術上鑽牛角尖的話,好吧,這是賦值,不是初始化)。是故,我們能夠保證`environment`物件的數量不會超過乙個。請注意,`environment`型別沒有給予其建構函式public訪問層級,所以`environment`型別的使用者只能用它公開出來的`instance()`成員函式來取得這個靜態指標。而且,我們不必在第一次訪問`environment`物件之前就建立它11:

`environment::instance().op1();`

c 全域性變數 靜態全域性變數

全域性變數是靜態儲存方式,靜態全域性變數也是靜態儲存方式,這兩者在儲存方式上並無不同。區別 雖在於非靜態全域性變數的作用域是整個源程式,當乙個源程式由多個原始檔組成時,靜態全域性變數在各個原始檔中都是有效的。靜態區域性變數則限制了其作用域,只在定義該變數的原始檔內有效,在同一源程式的其它原始檔中不能...

C 全域性變數

c 工程有以下幾個檔案 標頭檔案 a.h,b.h 相應的cpp檔案 a.cpp 包含a.h b.cpp 包含b.h 以及其他一些相關的.h,cpp檔案。a中有類a,b中有類b。現在需要在b.cpp中使用a.cpp 類a中的乙個變數,且希望其是隨著a.cpp 類a的呼叫更新的值。可按如下操作 在a.h...

c全域性變數

c語言中全域性變數可以重複定義 include int g val int g val 1 int main void 執行結果 1 include int g val 2 int g val int main void 執行結果 2 include int g val 2 int g val 1 ...