2010-08-05 65 views
5

這是previous question of mine範圍的擴展。當在C++中聲明「全局」變量時,「static」是什麼意思?

究竟是什麼「靜態」,它是如何使用的,以及在處理C++時使用「靜態」的目的是什麼?

謝謝。

+2

但「前一個問題」是關於Java ... – kennytm 2010-08-05 16:07:51

+4

取決於你在談論哪種靜態用法。我最喜歡的引號之一。 「直到他們發現靜態的新用法,它纔是C++的新版本」 – JaredPar 2010-08-05 16:07:54

+0

@Kenny ......是的,我知道。這就是爲什麼我想擴大考慮C/C++的範圍。我用Java得到了答案,我想知道在處理C/C++時它是否會有所不同。 – Hristo 2010-08-05 16:09:18

回答

10

關鍵字static在C++中有不同的含義,具體取決於上下文。

在聲明無功能或全局變量這意味着該函數是不是要這個單一翻譯單元外提供:

// test.cpp 
static int a = 1; 
static void foo() {} 

如果在編譯的翻譯單元的結果與一個不同的鏈接包含符號的翻譯單元afoo它不會破壞一個定義規則,因爲在這個特定的翻譯單元afoo私人符號。這種用法已被未命名的名稱空間廢棄。

// test2.cpp 
namespace { 
    static int a = 1; 
    static void foo() {} 
} 

當聲明一個函數內的局部變量表示該變量的生存期將從第一呼叫延伸到所述功能到節目的結束,並且不僅對呼叫的持續時間:

int foo() { 
    static int counter = 0; 
    return ++counter; 
} 
int main() { 
    for (int i = 0; i < 10; ++i) { 
    std::cout << foo() << std::endl; 
    } 
} 

在上面的代碼,當foo被稱爲首次counter被初始化一次,但變量會活得比的功能,並保持在不同的函數調用的值。前面的代碼將打印「1 2 3 4 ... 10」。如果該變量未被聲明爲static那麼輸出將是「1 1 1 ... 1」。

在類範圍內,static表示成員是類的成員,而不是特定實例的成員。這種用法相當於您在其他問題中的用法:該特定成員的使用不受任何特定對象的約束。

struct test { 
    int x; 
    static int y; 
}; 
int test::y;  // need to define it in one translation unit 
int main() { 
    // test::x = 5; // !error cannot access a non-static member variable 
        // without an instance 
    test::y = 5; // ok 
    test t, other; 
    t.x = 10;  // ok 
    t.y = 15;  // ok, the standard allows calling a static member through 
        // an instance, but this is the same as test::y 
} 

在這種情況下,構件x是一個非靜態成員屬性,並且因此存在用於類的每個實例不同x。示例程序t.xother.x指的是不同的整數。另一方面,ystatic,因此程序中有一個test::y的實例。即使標準允許呼叫t.yother.y這兩種用途都引用相同的變量。成員方法也是如此。如果它們是靜態的,它們是類級別的方法,可以在沒有實例的情況下調用,而如果它們是非靜態的,它們將應用於具體實例,並且必須使用a.ba->b語法。

static的這種用法類似於在Java中使用相同的關鍵字,而其他兩種不存在於該語言中。 Java中有一個關鍵字在C++中不存在,那就是使用靜態類初始值設定項(類級別的代碼塊包圍在static { ... }之內)。在Java中,代碼塊將在類加載時執行並且只會執行一次。在C++中初始化靜態成員變量必須在變量定義的初始化程序中完成。

+1

在您的第二個代碼片段中,是不是您恰好意味着要移除「static」的使用? – 2016-03-17 03:22:43

13

這意味着該變量對於翻譯單元是本地的(簡單地放在單個源文件中),並且不能從外部訪問它。這個使用靜態的其實是在當前的C++標準棄用 - 而不是你應該使用匿名的命名空間:

static int x = 0;  

應該是:

namespace { 
    int x = 0;  
} 
+0

1.什麼是翻譯單位? 2.這個想法在處理類時如何工作? – Hristo 2010-08-05 16:11:54

+2

匿名命名空間的東西真的需要打到人們的頭上。有太多的C++程序員在15年前學習C++,從那時起就沒有學過任何東西。 – 2010-08-05 16:12:38

+0

@Hristo類不能是靜態的,但它們的實例可以是。 – 2010-08-05 16:14:14

2

靜態基本上意味着一個變量是聯繫在一起的程序的生命週期,而不是任何給定的函數或類實例。你應該什麼時候使用它?別。什麼目的?主要是調試數據。

通常,在C++中,如果您發現自己使用靜態數據,那麼您做錯了。有些時候它是合適的,但它們非常罕見。

+0

..哈哈:)不要使用靜態。很容易記住。你有什麼要說尼爾的答案?另外,您的建議是否也適用於C? – Hristo 2010-08-05 16:19:49

+0

@Hristo:是的。另外,尼爾的答案並沒有錯。爲了達到目的,靜態已被取代。這並不意味着它起到了有用的作用。這就是那種地方,有些東西在沒有靜電的情況下是非常不可能的。但是,新程序員可能會過度使用它,應該儘可能地避免它,而那些真正需要的東西則非常罕見。 – Puppy 2010-08-05 16:24:24

+0

感謝您的澄清。 – Hristo 2010-08-05 16:25:11

6

這東西似乎覆蓋得很好here

但是套用,有2種用途用C

  1. 防止定義它的文件的範圍之外使用全局變量的。
  2. 允許的函數內的局部變量堅持翻過功能的調用,如在

    INT getNextId() { 靜態INT ID = 0; return id ++; }

C++繼承了這兩者,並增加了它自己的兩種用法。

  1. 靜態成員變量:在類的所有實例中「共享」的變量,也可以在不參考類的實例的情況下訪問。共享似乎是錯誤的詞,但實際上,我相信結果是任何對靜態成員變量的引用都引用相同的內存位置。
  2. 靜態方法:可以在不參考定義它的類的特定實例的情況下調用的方法。
+0

結構合理的答案!感謝您的迴應和參考。從你的回答看來,C++中的「static」與Java沒有多大區別。 – Hristo 2010-08-05 16:42:48

+1

@Hristo:Java只有最後兩種情況。第一個和第二個用例(C部分)不能在那裏使用。 – 2010-08-05 17:40:55

+0

@大衛......哦,好的。謝謝。順便說一句...當我有更多時間專注於適當的焦點時,我會閱讀你的正式答案。感謝您抽出寶貴的時間! – Hristo 2010-08-05 17:45:50

0

靜態類成員是與類本身相關聯的數據和函數,而不是類的對象。

在以下示例中,Fred類具有靜態數據成員x_和實例數據成員y_。無論創建多少個Fred對象(包括沒有Fred對象),只有Fred :: x_的一個副本,但每個Fred對象有一個y_。因此,x_被認爲與類相關聯,並且y_被認爲與該類的單個對象相關聯。同樣,Fred類有一個靜態成員函數f()和一個實例成員函數g()。

class Fred { 
    public: 
     static void f() throw();       <-- 1 
     void g() throw();         <-- 2 
    protected: 
     static int x_;          <-- 3 
     int y_;           <-- 4 
}; 
與類相關

(1)成員函數

與類的單個對象相關聯的

(2)成員函數

與類

相關

(3)數據成員(4)與該類別的個別對象關聯的數據成員

用法:

當您想保留創建的類的實例數量時,使用靜態變量。例如,在「汽車」類中,每個Car實例可能都有一個唯一的序列號(在這種情況下爲_y),並且公司可能需要跟蹤生產的汽車數量(本例中爲_x)。

+0

結構很好的答案!感謝您的迴應和參考。從你的回答看來,C++中的「static」與Java沒有多大區別。 – Hristo 2010-08-05 16:43:30

+0

儘管這並沒有真正回答原來的問題......這隻能解釋類的上下文中的靜態。不是全球範圍。 對於全局範圍,它的處理方式與C完全相同。 – 2010-08-05 17:11:21

1

當在C++中使用靜態類時,它意味着它在Java中的作用差不多。對於變量來說,它意味着變量的一個實例存在於所有類和函數中,這意味着該函數根本不隱式訪問該指針。

在靜態用於全局變量或函數的C和C++中,則表示該變量只能在當前的C或C++文件中引用。換句話說,編譯器不能爲變量或函數生成任何重定位符號。

當本地函數中的變量旁邊使用了靜態時,這意味着該變量不會超出範圍,但會保留其從函數調用到函數調用的值。該變量實際上成爲只能從給定函數訪問的全局變量。