C++: static

C++: static

1 人贊了文章

  • 限制作用域: static全局變數和函數,其作用域為當前cpp文件,其它的cpp文件不能訪問該變數和函數
  • 類的static 數據成員/成員函數: 表示屬於一個類而不是屬於此類的任何特定對象的變數和函數。比如在對某一個類的對象進行計數時, 計數生成多少個類的實例, 就可以用到靜態數據成員

-----------------------------------------------

c/c++ static 用法總結(三版本合一)

static

2、限制作用域

這一點相對於普通全局變數static全局變數來說的。

對於全局變數而言,不論是普通全局變數還是static全局變數,其存儲區都是靜態存儲區

因此在內存分配上沒有什麼區別

區 別在於:

1) 普通的全局變數和函數,其作用域為整個程序或項目,外部文件(其它cpp文件)可以

通過extern關鍵字訪問該變數和函數。一般不提倡這種用法,如果要在多個cpp文件間共享

數據,應該將數據聲明為extern類型。

在頭文件里聲明為extern:

extern int g_value; // 注意,不要初始化值!

然後在其中任何一個包含該頭文件的cpp中初始化(一次)就好:

int g_value = 0; // 初始化一樣不要extern修飾,因為extern也是聲明性關鍵字;

然後所有包含該頭文件的cpp文件都可以用g_value這個名字訪問相同的一個變數

2) static全局變數和函數,其作用域為當前cpp文件,其它的cpp文件不能訪問該變數和

函數。如果有兩個cpp文件聲明了同名的全局靜態變數,那麼他們實際上是獨立的兩個變數.

static函數的好處是不同的人編寫不同的函數時,不用擔心自己定義的函數,是否會與其

它文件中的函數同名。

頭文件中的static變數

如果在一個頭文件中聲明:

static int g_vaule = 0;

那麼會為每個包含該頭文件的cpp都創建一個全局變數,但他們都是獨立的;所以也

不建議這樣的寫法,一樣不明確需要怎樣使用這個變數,因為只是創建了一組同名而不同

作用域的變數.

3、數據唯一性

static data member, static method in class

a.hclass A {....private: A my_map_ = new std::unordered_map<string, string>;}a.cc void A::f() {my_map_->insert(..);} will cause memory leakage, because every time a instance of A is created, memory is allocated. Need to use static, only allocate once, and shared among instances of class A.a.hclass A {....private: A my_map_;}//a.cc static A::my_map_ = new std::unordered_map<string, string>;void A::GenerateMyMap() { my_map_->insert(..);}

Its better to just initiate the map while defining it.

//module.ccnamespace youku {namespace scoring {using DataSource;namespace {const std::unordered_map<string, string>& GenerateMap() { // This map will be initiated only one time. And shared among instances of this class static auto* map = new std::unordered_map<string, string>({{"key1", "val1"}, {"key2", "val2"}});return *map;}} // namespaceMyClass::MyMethod() { const auto* val = FindOrNull(GenerateMap(), "key1"); }} // namespace scoring} // namespace youku

這是C++對static關鍵字的重用。主要指靜態數據成員/成員函數。

表示屬於一個類而不是屬於此類的任何特定對象的變數和函數. 這是與普通成員函數的最

大區別, 也是其應用所在, 比如在對某一個類的對象進行計數時, 計數生成多少個類的實

例, 就可以用到靜態數據成員. 在這裡面, static既不是限定作用域的, 也不是擴展生存

期的作用, 而是指示變數/函數在此類中的唯一性. 這也是」屬於一個類而不是屬於此類的

任何特定對象的變數和函數」的含義. 因為它是對整個類來說是唯一的, 因此不可能屬於

某一個實例對象的. (針對靜態數據成員而言, 成員函數不管是否是static, 在內存中只有

一個副本, 普通成員函數調用時, 需要傳入this指針, static成員函數調用時, 沒有this

指針. )

static數據成員的初始化:

(1) 初始化在類體外進行,而前面不加static,以免與一般靜態變數或對象相混淆。

(2) 初始化時不加該成員的訪問許可權控制符private,public等。

(3) 初始化時使用作用域運算符來標明它所屬類,因此,靜態數據成員是類的成員,而不

是對象的成員。

(4) 靜態數據成員是靜態存儲的,它是靜態生存期,必須對它進行初始化

Static成員函數

靜態成員函數和靜態數據成員一樣,它們都屬於類的靜態成員,它們都不是對象成員。因

此,對靜態成員的引用不需要用對象名

靜態成員函數僅能訪問靜態的數據成員,不能訪問非靜態的數據成員,也不能訪問非靜態

的成員函數,這是由於靜態的成員函數沒有this指針。

------------------

(1)先來介紹它的第一條也是最重要的一條:隱藏。

當我們同時編譯多個文件時,所有未加static前綴的全局變數和函數都具有全局可見性。為理解這句話,我舉例來說明。我們要同時編譯兩個源文件,一個是a.c,另一個是main.c。

下面是a.c的內容

char a = A; // global variablevoid msg(){ printf("Hello
");}

下面是main.c的內容

int main(void){ extern char a; // extern variable must be declared before use printf("%c ", a); (void)msg(); return 0;}

程序的運行結果是:

A Hello

你可能會問:為什麼在a.c中定義的全局變數a和函數msg能在main.c中使用?前面說過,所有未加static前綴的全局變數和函數都具有全局可見性其它的源文件也能訪問。此例中,a是全局變數,msg是函數,並且都沒有加static前綴,因此對於另外的源文件main.c是可見的。

如果加了static,就會對其它源文件隱藏。例如在a和msg的定義前加上static,main.c就看不到它們了。利用這一特性可以在不同的文件中定義同名函數和同名變數,而不必擔心命名衝突。Static可以用作函數和變數的前綴,對於函數來講,static的作用僅限於隱藏,而對於變數,static還有下面兩個作用。

(2)static的第二個作用是保持變數內容的持久。存儲在靜態數據區的變數會在程序剛開始運行時就完成初始化,也是唯一的一次初始化共有兩種變數存儲在靜態存儲區全局變數和static變數,只不過和全局變數比起來,static可以控制變數的可見範圍,說到底static還是用來隱藏的。雖然這種用法不常見,但我還是舉一個例子。

#include <stdio.h>int fun(void){ static int count = 10; // local static return count--;}int count = 1; // globalint main(void){ printf("global local static
"); for(; count <= 10; ++count) printf("%d %d
", count, fun()); return 0;}

程序的運行結果是:

global local static1 102 93 84 75 66 57 48 39 210 1

(3)static的第三個作用是默認初始化為0。其實全局變數也具備這一屬性,因為全局變數也存儲在靜態數據區。在靜態數據區,內存中所有的位元組默認值都是0x00某些時候這一特點可以減少程序員的工作量。比如初始化一個稀疏矩陣,我們可以一個一個地把所有元素都置0,然後把不是0的幾個元素賦值。如果定義成靜態的,就省去了一開始置0的操作。再比如要把一個字元數組當字元串來用,但又覺得每次在字元數組末尾加』』太麻煩。如果把字元串定義成靜態的,就省去了這個麻煩,因為那裡本來就是』』。不妨做個小實驗驗證一下。

#include <stdio.h>int a;int main(void){ int i; static char str[10]; printf("integer: %d; string: (begin)%s(end)", a, str); return 0;}

程序的運行結果如下

integer: 0; string: (begin)(end)

最後對static的三條作用做一句話總結。首先static的最主要功能是隱藏,其次因為static變數存放在靜態存儲區,所以它具備持久性和默認值0。

推薦閱讀:

php 與C/C++ 集成的方法有哪些?
簡析 Python 的 `NotImplemented`
字元指針數組的使用--替換人名-題目分析
C#中使用Lambda表達式簡化代碼

TAG:編程語言 | 編程 | C |