精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

面試官最愛問的 static 陷阱:答對薪資翻倍,答錯直接掛科!

開發(fā)
在 C/C++的編程實踐中,static 關(guān)鍵字猶如瑞士軍刀般存在,它能夠控制變量和函數(shù)的生命周期、作用域、存儲方式,還能在面向?qū)ο缶幊讨袑崿F(xiàn)類級別的共享特性。

static 關(guān)鍵字在 C/C++當(dāng)中非常非常重要,有多重要,我們先看看幾位大佬的說法:

  • 《Linux 多線程服務(wù)端編程》作者 陳碩 在書籍中多次強(qiáng)調(diào):"正確理解 static 的語義,是寫出高質(zhì)量 C++代碼的基本功"。
  • 《現(xiàn)代 C++編程實戰(zhàn)》作者 吳詠煒 在書籍中指出:"static 的正確使用是區(qū)分 C++程序員水平的重要標(biāo)尺"。
  • Linux 內(nèi)核開發(fā)者 Robert Love 曾說:"真正理解 static 的程序員,已經(jīng)跨過了從語言使用者到系統(tǒng)設(shè)計者的門檻"。

static 關(guān)鍵字是一個看著簡單,其實有很多知識點的核心機(jī)制??梢哉f在 C/C++的編程實踐中,static 關(guān)鍵字猶如瑞士軍刀般存在,它能夠控制變量和函數(shù)的生命周期、作用域、存儲方式,還能在面向?qū)ο缶幊讨袑崿F(xiàn)類級別的共享特性。今天我們來一起復(fù)習(xí)下:萬字長文,建議收藏!

一、 C 語言中的 static

在 C 語言中,static 主要有兩種截然不同的含義,取決于它所修飾的對象(變量或函數(shù))的位置:

1. 文件作用域的 static:內(nèi)部鏈接

當(dāng) static 用于修飾在函數(shù)外部定義的全局變量或函數(shù)時,它的核心作用是改變鏈接屬性,將其從默認(rèn)的外部鏈接改為內(nèi)部鏈接。

  • 外部鏈接:默認(rèn)情況下,全局變量和函數(shù)具有外部鏈接。這意味著它們不僅在當(dāng)前源文件(編譯單元,Translation Unit)中可見,而且可以被其他源文件通過 extern 聲明來訪問和使用。鏈接器(Linker)在鏈接多個目標(biāo)文件時,會解析這些具有外部鏈接的符號名,確保它們在整個程序中是唯一的(或者說,定義只有一個)。
  • 內(nèi)部鏈接:使用 static 修飾后,全局變量或函數(shù)的名字將只在當(dāng)前的源文件中可見。其他源文件即使使用 extern 聲明也無法訪問到它們。鏈接器在處理具有內(nèi)部鏈接的符號時,不會將它們暴露給其他編譯單元。

為什么需要內(nèi)部鏈接?

  • 避免命名沖突:在一個大型項目中,不同的模塊(源文件)可能會無意中定義相同名稱的全局變量或輔助函數(shù)。如果它們都具有外部鏈接,鏈接器會報告“符號重定義”錯誤。將只在模塊內(nèi)部使用的全局變量和函數(shù)聲明為 static,可以有效地將它們“隱藏”起來,避免與其他模塊的同名符號沖突。這是一種基本的封裝手段。
  • 限制作用域,提高模塊化:明確告知其他開發(fā)者(以及編譯器和鏈接器),這個變量或函數(shù)是本模塊內(nèi)部使用的,不應(yīng)被外部直接依賴。這有助于降低模塊間的耦合度,提高代碼的可維護(hù)性。

示例:

// module_a.c
#include <stdio.h>

static int s_a= 0; // 內(nèi)部鏈接的全局變量,僅 module_a.c 可見
int g_b= 10;        // 外部鏈接的全局變量(默認(rèn))

static void func() {   // 內(nèi)部鏈接的函數(shù),僅 module_a.c 可見
    printf("func: %d\n", ++s_a);
}

void func2() {               // 外部鏈接的函數(shù)(默認(rèn))
    printf("func2: %d\n", g_b);
}

// module_b.c
#include <stdio.h>

// extern int s_a; // 嘗試訪問,鏈接時會失敗!error: undefined reference to `s_a`
extern int g_b;      // 可以訪問 module_a.c 中的 g_b

// extern void func(); // 嘗試訪問,鏈接時會失??!error: undefined reference to `func`
extern void func2();         // 可以調(diào)用 module_a.c 中的 func2

int main() {
    printf("g_b: %d\n", g_b);
    func2(); // 調(diào)用 module_a 的公共函數(shù)
    // func(); // 直接調(diào)用或通過 extern 聲明調(diào)用都會失敗
    return0;
}

在這個例子中,s_a 和 func 因為 static 的修飾,被牢牢地限制在了 module_a.c 內(nèi)部,module_b.c 無法直接觸及它們,從而保證了 module_a.c 的內(nèi)部實現(xiàn)細(xì)節(jié)不被外部干擾,也避免了潛在的命名沖突。

類比思考: 

可以將源文件想象成一個房間,static 全局變量/函數(shù)就像是房間里的私人物品,只有房間內(nèi)的人(代碼)可以使用。而沒有 static 的全局變量/函數(shù)就像是放在公共走廊上的物品,所有房間的人(其他源文件)都可能看到和使用(如果知道名字的話)。

2. 函數(shù)作用域的 static:靜態(tài)存儲期

當(dāng) static 用于修飾在函數(shù)內(nèi)部定義的局部變量時,它的含義完全不同。它不再影響鏈接屬性(局部變量本來就沒有鏈接屬性),而是改變變量的存儲期。

(1) 自動存儲期

默認(rèn)情況下,函數(shù)內(nèi)的局部變量具有自動存儲期。它們在程序執(zhí)行進(jìn)入其作用域(通常是函數(shù)體或代碼塊)時被創(chuàng)建和初始化,在退出作用域時被銷毀。每次函數(shù)調(diào)用都會創(chuàng)建新的實例,它們的值在函數(shù)調(diào)用之間不會保留。它們通常存儲在棧上。

(2) 靜態(tài)存儲期

使用 static 修飾后,局部變量將具有靜態(tài)存儲期。這意味著:

  • 生命周期延長:變量在程序第一次執(zhí)行到其定義時被創(chuàng)建和初始化,并且會一直存活到程序結(jié)束。它的內(nèi)存通常分配在靜態(tài)存儲區(qū)(.data 或 .bss 段),而不是棧上。
  • 僅初始化一次:盡管定義語句可能在函數(shù)中,看起來每次調(diào)用都會執(zhí)行,但帶有 static 的局部變量的初始化只會在整個程序生命周期內(nèi)發(fā)生一次(通常是在第一次執(zhí)行到該定義時)。
  • 值在調(diào)用間保持:由于變量的生命周期貫穿程序始終,它在函數(shù)調(diào)用結(jié)束后不會被銷毀,其值會保留到下一次函數(shù)調(diào)用。

為什么需要靜態(tài)局部變量?

  • 維護(hù)狀態(tài):需要在函數(shù)多次調(diào)用之間保持某個狀態(tài),例如計數(shù)器、緩存、標(biāo)志位等。
  • 避免重復(fù)初始化開銷:如果一個局部變量的初始化比較昂貴(例如,需要計算或分配資源),但其值在后續(xù)調(diào)用中應(yīng)保持不變,使用 static 可以確保初始化只進(jìn)行一次。
  • 簡單的單例模式(C 風(fēng)格):雖然不完全是面向?qū)ο蟮膯卫梢杂脕泶_保某個資源或?qū)ο笤诤瘮?shù)內(nèi)部只被創(chuàng)建一次。

示例:

#include <stdio.h>
void counter_function() {
    static int call_count = 0; // 靜態(tài)局部變量,只初始化一次
    int auto_var = 0;          // 自動局部變量,每次調(diào)用都重新初始化

    call_count++;
    auto_var++;

  printf("Static count: %d, Auto var: %d\n", call_count, auto_var);
}
int main() {
    printf("Calling counter_function first time:\n");
    counter_function();

    printf("\nCalling counter_function second time:\n");
    counter_function();

    printf("\nCalling counter_function third time:\n");
    counter_function();
    return0;
}
/*
輸出:
Calling counter_function first time:
Static count: 1, Auto var: 1

Calling counter_function second time:
Static count: 2, Auto var: 1

Calling counter_function third time:
Static count: 3, Auto var: 1
*/

可以看到,call_count 的值在每次函數(shù)調(diào)用后都得以保留并累加,而 auto_var 則在每次調(diào)用時都重置為 1。這就是靜態(tài)存儲期和自動存儲期的關(guān)鍵區(qū)別。

注意事項:

在 C 語言的多線程環(huán)境中,如果多個線程同時調(diào)用包含靜態(tài)局部變量初始化的函數(shù),其初始化過程可能不是線程安全的(取決于編譯器實現(xiàn)和 C 標(biāo)準(zhǔn)版本,C11 之前沒有強(qiáng)制規(guī)定)。競態(tài)條件可能導(dǎo)致變量被初始化多次或初始化不完整。C++11 及之后對此有明確的線程安全保證(稍后詳述)。

總結(jié):

C 語言當(dāng)中的 static 其實就兩個功能:

  • 第一:對于全局的(變量和函數(shù))改變鏈接屬性
  • 第二:對于局部的(只有變量)改變生存周期。

注意的是,static 全局內(nèi)容不要放在頭文件,我們需要知道,頭文件用于共享聲明,這里重點是共享,而 static 全局內(nèi)容用于修改鏈接屬性為內(nèi)部鏈接,反對共享!這兩者本質(zhì)上就是相對的。

雖然 static 全局內(nèi)容放到了頭文件不會出錯,但是會導(dǎo)致所有引用這個頭文件的翻譯單元都會有一份副本。這么寫,很大可能是對 static 理解不到位,一般沒有任何意義,達(dá)不到預(yù)想的效果。

如果你是想要所有翻譯單元訪問同一份資源,那應(yīng)該用 extern 頭文件聲明+源文件定義的方式。

如果你是想要各自翻譯單元有自己的資源,但是資源名字一樣,那么應(yīng)該在源文件中分別定義自己的 static 全局資源(這個也不是推薦的寫法)。

二、 C++ 中的 static

C++ 完全繼承了 C 語言中 static 的上述兩種用法(內(nèi)部鏈接和靜態(tài)局部變量),但也對其進(jìn)行了一些演進(jìn),并賦予了它在類(Class)中的全新、重要的含義。

1. 繼承自 C 的用法及其演進(jìn)

內(nèi)部鏈接(文件/命名空間作用域):

  • static 仍然可用:你仍然可以在 C++ 的全局作用域或命名空間作用域使用 static 來定義具有內(nèi)部鏈接的變量和函數(shù)。其效果與 C 語言中完全相同。
  • 匿名命名空間是更推薦的方式:然而,在 C++ 中,強(qiáng)烈推薦使用匿名命名空間來替代 static 實現(xiàn)內(nèi)部鏈接。
// C++ 推薦方式: 匿名命名空間
namespace { // <--- 匿名命名空間開始
    int internal_counter = 0; // 默認(rèn)具有內(nèi)部鏈接

    void internal_helper() {  // 默認(rèn)具有內(nèi)部鏈接
        // ...
    }
} // <--- 匿名命名空間結(jié)束

// C++ 不推薦方式 (但仍然有效): static
// static int old_style_counter = 0;
// static void old_style_helper() { /* ... */ }

void public_api() {
    internal_helper(); // 可以直接調(diào)用同一編譯單元內(nèi)的匿名命名空間成員
}

為什么使用匿名命名空間:

  • 一致性:它使用 C++ 的核心語言特性(命名空間)來解決作用域問題,而不是依賴一個具有多重含義的關(guān)鍵字。
  • 適用性更廣:匿名命名空間不僅可以用于變量和函數(shù),還可以用于類型定義(如 class, struct, enum, typedef, using 別名等)。static 不能用于限制類型的鏈接屬性。
  • 清晰性:代碼意圖更明確,namespace { ... } 清晰地標(biāo)示出一塊內(nèi)部使用的區(qū)域。
  • 避免 static 歧義:減少 static 關(guān)鍵字的負(fù)擔(dān),讓它主要承擔(dān)在類中和函數(shù)內(nèi)的角色。

正如吳詠煒老師可能強(qiáng)調(diào)的,擁抱現(xiàn)代 C++ 的實踐,選擇更清晰、更通用的語言特性。

靜態(tài)局部變量(函數(shù)作用域):

  • 用法和 C 類似:在 C++ 函數(shù)內(nèi)部使用 static 定義局部變量,其效果(靜態(tài)存儲期、僅初始化一次、值在調(diào)用間保持)與 C 語言基本一致。
  • C++11 及以后的線程安全初始化保證(Magic Statics):這是一個重大的改進(jìn)。C++11 標(biāo)準(zhǔn)規(guī)定,靜態(tài)局部變量的初始化是線程安全的。這意味著即使多個線程可能同時首次執(zhí)行到該 static 變量的定義處,C++ 運行時環(huán)境會確保初始化過程只發(fā)生一次,并且其他線程會等待初始化完成后才能繼續(xù)執(zhí)行。這極大地簡化了在多線程環(huán)境下使用靜態(tài)局部變量(例如實現(xiàn)線程安全的單例模式)的代碼。

示例:

#include <iostream>
#include <thread>
#include <vector>

class Singleton {
public:
    static Singleton& getInstance() {
        // C++11 guarantees thread-safe initialization for function-local statics
        static Singleton instance; // "Magic Static"
        std::cout << "獲取單例線程:thread " << std::this_thread::get_id() << std::endl;
        return instance;
    }

    void showMessage() {
        std::cout << "單例調(diào)用:(" << this << ") says hello!" << std::endl;
    }

private:
    Singleton() {
        // Simulate complex initialization
        std::cout << "單例創(chuàng)建: thread "
            << std::this_thread::get_id() << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    ~Singleton() = default;
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};

void worker() {
    Singleton::getInstance().showMessage();
}

int main() {
    std::vector<std::thread> threads;
    std::cout << "Creating threads..." << std::endl;
    for (int i = 0; i < 5; ++i) {
        threads.emplace_back(worker);
    }

    for (auto& t : threads) {
        t.join();
    }
    std::cout << "All threads finished." << std::endl;
    return0;
}

運行輸出:(VS2022)

Creating threads...
單例創(chuàng)建: thread39972
獲取單例線程:thread25656
單例調(diào)用:(00007FF79E478440)sayshello!
獲取單例線程:thread39708
單例調(diào)用:(00007FF79E478440)sayshello!
獲取單例線程:thread39972
單例調(diào)用:(00007FF79E478440)sayshello!
獲取單例線程:thread5280
單例調(diào)用:(00007FF79E478440)sayshello!
獲取單例線程:thread1744
單例調(diào)用:(00007FF79E478440)sayshello!
Allthreadsfinished.

2. C++ 類(Class)中的 static

這是 static 在 C++ 中獨有的、至關(guān)重要的用法。當(dāng) static 用于修飾類的成員時,它表示該成員屬于類本身,而不是類的任何特定對象(實例)。

靜態(tài)成員變量:

  • 共享性:靜態(tài)成員變量是該類所有對象共享的。無論創(chuàng)建了多少個類的對象,或者即使沒有創(chuàng)建任何對象,靜態(tài)成員變量都只有一份內(nèi)存副本。
  • 生命周期:它們具有靜態(tài)存儲期,在程序啟動時(或首次使用前,取決于具體情況和編譯優(yōu)化)被創(chuàng)建和初始化,直到程序結(jié)束才銷毀。它們不存儲在對象實例的內(nèi)存布局中。
  • 作用域:它們屬于類的作用域,訪問時需要使用類名和作用域解析運算符 ::(ClassName::staticVar),或者通過類的對象或指針/引用訪問(object.staticVar 或 ptr->staticVar),但推薦使用類名訪問以強(qiáng)調(diào)其類成員的身份。

定義與初始化:

  • 通常需要在類定義外部進(jìn)行定義和初始化。在類定義內(nèi)部只是聲明。這一定義通常放在對應(yīng)的 .cpp 源文件中,以確保它只被定義一次(符合 ODR - One Definition Rule)。
  • 例外:const static 整型/枚舉成員(C++11 前)或 constexpr static 成員(C++11 起):如果一個靜態(tài)成員變量是 const 的整型(int, char, bool 等)或枚舉類型,可以在類定義內(nèi)部直接初始化。C++11 引入 constexpr 后,constexpr static 成員也可以在類內(nèi)部初始化(且其值在編譯期可知)。
  • C++17 的 inline static 成員:C++17 引入了 inline 關(guān)鍵字用于靜態(tài)成員變量,允許在類定義內(nèi)部直接完成定義和初始化,即使對于非 const 或非 constexpr 的類型。這極大地簡化了靜態(tài)成員變量的使用,尤其是在頭文件(header-only)庫中。

示例:

// counter.h
class ObjectCounter {
public:
    ObjectCounter() {
        s_count++; // 對象創(chuàng)建時,共享計數(shù)器加 1
    }
    ~ObjectCounter() {
        s_count--; // 對象銷毀時,共享計數(shù)器減 1
    }

    // 聲明靜態(tài)成員變量
    static int s_count;

    // C++17: inline static member (可在頭文件定義和初始化)
    inline static double s_version = 1.0;

    // const static integral member (可在類內(nèi)初始化)
    const static int s_maxObjects = 100;

    // constexpr static member (C++11, 可在類內(nèi)初始化, 編譯期常量)
    constexpr static const char* s_typeName = "ObjectCounter";

    static int getCount() { return s_count; } // 靜態(tài)成員函數(shù)訪問靜態(tài)成員變量
};

// counter.cpp (如果不用 inline static,需要在這里定義非 const/constexpr static 成員)
// #include "counter.h"
// int ObjectCounter::s_count = 0; // 定義并初始化 s_count

用途: 類范圍的常量、所有對象共享的狀態(tài)(如對象計數(shù)器、共享資源指針)、配置參數(shù)等。

靜態(tài)成員函數(shù):

  • 屬于類,不依賴對象:靜態(tài)成員函數(shù)也是屬于類本身的,調(diào)用它們不需要創(chuàng)建類的對象。
  • 無 this 指針:最關(guān)鍵的區(qū)別在于,靜態(tài)成員函數(shù)沒有隱式的 this 指針。因為它們不與任何特定對象關(guān)聯(lián)。
  • 訪問限制:由于沒有 this 指針,靜態(tài)成員函數(shù)不能直接訪問類的非靜態(tài)成員(變量或函數(shù))。它們只能直接訪問類的其他靜態(tài)成員(靜態(tài)變量和靜態(tài)函數(shù))。如果需要訪問非靜態(tài)成員,必須通過傳遞一個對象實例的引用或指針來實現(xiàn)。
  • 調(diào)用方式:通常使用類名和作用域解析運算符 :: 調(diào)用(ClassName::staticFunc())。也可以通過對象或指針/引用調(diào)用(object.staticFunc() 或 ptr->staticFunc()),但這會掩蓋其靜態(tài)本質(zhì),不推薦。

示例(續(xù)上例):ObjectCounter::getCount() 就是一個靜態(tài)成員函數(shù)。它不需要對象實例即可調(diào)用,并且它直接訪問了靜態(tài)成員變量 s_count。

// 在 main.cpp 或其他地方:
int currentCount = ObjectCounter::getCount(); // 正確調(diào)用

另一個例子:工廠方法

#include <string>
#include <memory>
class Resource {
public:
    // 靜態(tài)工廠方法
    static std::unique_ptr<Resource> create(const std::string& type) {
        if (type == "TypeA") {
            return std::unique_ptr<Resource>(new Resource("Created TypeA"));
        } else if (type == "TypeB") {
            return std::unique_ptr<Resource>(new Resource("Created TypeB"));
        }
        return nullptr;
    }
    void use() { /* ... use resource ... */ }
    const std::string& getInfo() const { return info_; }
private:
    // 私有構(gòu)造函數(shù),強(qiáng)制通過工廠方法創(chuàng)建
    Resource(std::string info) : info_(std::move(info)) {}
    std::string info_;
    // 禁止拷貝和賦值
    Resource(const Resource&) = delete;
    Resource& operator=(const Resource&) = delete;
};
int main() {
    auto resA = Resource::create("TypeA"); // 使用靜態(tài)工廠方法創(chuàng)建對象
    if (resA) {
        std::cout << "Resource A info: " << resA->getInfo() << std::endl;
        resA->use();
    }
    auto resB = Resource::create("TypeB");
    if (resB) {
        std::cout << "Resource B info: " << resB->getInfo() << std::endl;
    }
    return 0;
}

在這個工廠模式的例子中,create 函數(shù)作為靜態(tài)成員函數(shù),負(fù)責(zé)根據(jù)輸入?yún)?shù)創(chuàng)建并返回 Resource 對象(通過智能指針管理)。它屬于 Resource 類,但調(diào)用時不需要先有一個 Resource 對象。

用途: 工具函數(shù)只操作靜態(tài)成員或與類概念相關(guān)但不需要對象狀態(tài)、工廠方法、管理靜態(tài)成員變量等。

類比思考: 

想象一個班級(Class。靜態(tài)成員變量就像是班級的公告欄(s_count),上面記錄著全班的總?cè)藬?shù),所有學(xué)生(對象)共享這個信息。靜態(tài)成員函數(shù)就像是班主任(getCount),他可以查看和更新公告欄信息,但他的行動不依賴于某個特定的學(xué)生(沒有 this)。而非靜態(tài)成員變量就像是每個學(xué)生的書包(instance_data),里面裝著各自的東西。非靜態(tài)成員函數(shù)就像是學(xué)生自己整理書包(instance_method()),需要明確是哪個學(xué)生(this)在操作自己的書包。

三、 static 用法異同點總結(jié)

用法上下文

C 語言

C++ 語言

核心含義/作用

文件/全局/命名空間作用域

static 全局變量/函數(shù): 內(nèi)部鏈接 (限制在當(dāng)前編譯單元)


1. static 全局/命名空間變量/函數(shù): 內(nèi)部鏈接 (效果同 C,但不推薦) 
 2. 匿名命名空間: 提供內(nèi)部鏈接 (C++ 推薦方式)

控制符號的可見性,避免命名沖突,實現(xiàn)封裝

函數(shù)內(nèi)部

static 局部變量: 靜態(tài)存儲期 (生命周期延長至程序結(jié)束,僅初始化一次)


static 局部變量:

1、靜態(tài)存儲期 (同 C) 
2、C++11 起保證線程安全初始化 

使局部變量在函數(shù)調(diào)用間保持狀態(tài),只初始化一次

C++ 類定義內(nèi)部

不適用

1. static 成員變量: 屬于類,所有對象共享,靜態(tài)存儲期 
2. static 成員函數(shù): 屬于類,無 this 指針,只能直接訪問靜態(tài)成員

定義類級別的屬性和行為,獨立于特定對象實例

四、 實踐中的考量與建議

(1) 優(yōu)先使用匿名命名空間而非 static 實現(xiàn)內(nèi)部鏈接 (C++):這是現(xiàn)代 C++ 的慣例。它更清晰、更通用,能覆蓋類型定義,且避免了 static 關(guān)鍵字的語義過載。static 在全局/命名空間作用域應(yīng)視為 C 的遺留用法。

(2) 警惕全局/命名空間作用域的 static 變量 (C/C++):雖然 static 或匿名命名空間能限制其鏈接性,但它們本質(zhì)上仍是全局狀態(tài)。全局狀態(tài)往往使程序的依賴關(guān)系復(fù)雜化,難以推理和測試,尤其在多線程環(huán)境下容易引入競態(tài)條件(除非精心設(shè)計同步)。陳碩在 muduo 庫的設(shè)計中就強(qiáng)調(diào)避免不必要的全局變量。優(yōu)先考慮將狀態(tài)封裝在對象中,通過參數(shù)傳遞或成員變量來管理。

(3) 善用函數(shù)內(nèi)的 static 變量 (C++):C++11 的線程安全初始化保證使其成為實現(xiàn)簡單單例或緩存的便捷方式。但要注意,它們的生命周期是整個程序,如果它們持有復(fù)雜資源(如文件句柄、網(wǎng)絡(luò)連接),需要考慮程序退出時的資源釋放問題(雖然通常操作系統(tǒng)會回收,但顯式管理更佳)。

(4) 靜態(tài)變量的初始化順序問題:如果一個靜態(tài)變量的初始化依賴于另一個編譯單元中的靜態(tài)存儲期變量(全局或局部),可能會遇到"靜態(tài)初始化順序災(zāi)禍" 。

// a.cpp
int global_var = initSomething();
// b.cpp
static int static_var = global_var;  // 危險!

記?。河肋h(yuǎn)不要在不同編譯單元之間建立靜態(tài)初始化依賴關(guān)系。

函數(shù)內(nèi)的靜態(tài)變量由于其延遲初始化(第一次調(diào)用時)特性,可以在一定程度上緩解這個問題,但跨編譯單元的依賴仍需小心。盡量避免復(fù)雜的靜態(tài)初始化依賴。C++標(biāo)準(zhǔn)明確規(guī)定:不同編譯單元中的全局變量和靜態(tài)變量的初始化順序是未定義的。

(5) 理解 static 類成員的生命周期和定義位置:切記非 inline、非 const static integral/constexpr static 的靜態(tài)成員變量需要在類外定義。忘記定義是常見的鏈接錯誤來源。C++17 的 inline static 簡化了這一點,值得在新代碼中采用。

(6) 明確 static 成員函數(shù)與非靜態(tài)成員函數(shù)的區(qū)別:核心在于 this 指針的有無。調(diào)用靜態(tài)成員函數(shù)時腦中要繃緊一根弦:它不屬于任何對象。這決定了它能訪問哪些成員。

(7) static 與 const / constexpr 結(jié)合:

  • static const 全局/命名空間變量:提供內(nèi)部鏈接的常量。
  • static constexpr (C++11): 提供內(nèi)部鏈接的編譯期常量。
  • static const 類成員:類范圍的運行時常量(若非整型/枚舉/inline/constexpr,需類外定義)。
  • static constexpr 類成員 (C++11): 類范圍的編譯期常量(可在類內(nèi)定義)。

五、 結(jié)語

理解 static 的每一種含義,區(qū)分它們在 C 和 C++ 中的細(xì)微差別(尤其是 C++11/17 帶來的改進(jìn)和類相關(guān)的用法),并遵循最佳實踐(如優(yōu)先使用匿名命名空間、注意線程安全、警惕全局狀態(tài)),是我們作為 C/C++ 開發(fā)者提升代碼質(zhì)量和設(shè)計能力的必經(jīng)之路。建議讀一讀陳碩大神的書籍,里面很多 static 的設(shè)計寫法值得學(xué)習(xí)!

責(zé)任編輯:趙寧寧 來源: CppPlayer
相關(guān)推薦

2025-06-30 01:55:00

2025-06-03 07:05:00

Linux操作系統(tǒng)Windows

2018-01-19 10:43:06

Java面試官volatile關(guān)鍵字

2021-03-17 08:39:24

作用域作用域鏈JavaScript

2025-03-18 12:00:00

閉包JavaScript前端

2025-02-10 00:00:25

內(nèi)存管理開發(fā)

2023-09-26 00:37:38

Spring微服務(wù)框架

2025-05-12 10:10:00

運維Linux系統(tǒng)

2025-09-03 04:25:00

MySQLFLOATDOUBLE

2021-12-25 22:31:10

MarkWord面試synchronize

2021-11-08 09:18:01

CAS面試場景

2021-12-16 18:38:13

面試Synchronize

2025-09-10 07:00:00

負(fù)載均衡Nginx運維

2020-07-28 00:58:20

IP地址子網(wǎng)TCP

2021-12-02 18:20:25

算法垃圾回收

2021-01-06 05:36:25

拉鏈表數(shù)倉數(shù)據(jù)

2010-08-23 15:06:52

發(fā)問

2022-01-05 09:55:26

asynawait前端

2021-04-21 09:28:17

字節(jié)面試官SetTimeout

2024-06-04 07:38:10

點贊
收藏

51CTO技術(shù)棧公眾號

特级西西444| 国产精品久久久久久久av大片| 日韩精品在线播放视频| a级片免费在线观看| 久久综合久久综合亚洲| 国产精品一区二区三区在线播放| 国产一级在线免费观看| 菠萝蜜一区二区| 精品国产1区二区| 韩国中文字幕av| 欧美6一10sex性hd| 国产精品区一区二区三| 国产精品久久久久免费| 九九热最新视频| 最新亚洲一区| 久热精品在线视频| 一区二区三区伦理片| xvideos.蜜桃一区二区| 欧美日韩黄色影视| 激情成人综合网| 欧美日韩黄色影视| 日本精品免费在线观看| www.久久av.com| www.综合网.com| 国产精品女上位| 欧美美乳视频网站在线观看| 午夜一级免费视频| 欧美精品一二三四区| 91精品一区国产高清在线gif| 亚洲成色777777女色窝| 韩国视频理论视频久久| 天堂а√在线中文在线鲁大师| 欧美亚洲大陆| 精品久久久久久久久久久久包黑料| 五月婷婷六月合| 免费成人动漫| 欧美日韩精品在线播放| 日本福利视频一区| 五月婷婷开心中文字幕| 激情小说一区| 欧美日韩亚洲另类| 农村妇女精品一二区| ririsao久久精品一区| 亚洲人成在线观看一区二区| 亚洲啪啪av| 国产国语老龄妇女a片| 成人黄色毛片| 欧美午夜一区二区| 国产一级片黄色| 欧美电影免费观看| 妖精视频在线观看免费| 国产成人免费| 欧美性色综合网| 999香蕉视频| 三级成人黄色影院| 在线观看亚洲成人| 高清一区在线观看| 欧洲精品久久久久毛片完整版| 欧美视频在线一区二区三区| 男人搞女人网站| 国产极品一区| 91精品国产综合久久精品app | 免费av成人在线| 国产精品人成电影在线观看| 在线免费观看av片| 国产精品乡下勾搭老头1| 成人精品水蜜桃| 午夜黄色小视频| 欧美—级在线免费片| 一本色道久久综合亚洲精品婷婷| 国产高清一区二区三区视频 | 国产精品xxxx喷水欧美| 久久午夜精品| 成人免费视频网址| 国产 日韩 欧美 精品| 99久久伊人网影院| 视频一区亚洲| 中文字幕中文字幕在线中高清免费版| 亚洲一区自拍偷拍| 国产精品亚洲a| 日韩美香港a一级毛片| 日韩美女天天操| 欧美成人午夜精品免费| 日韩精品网站| 欧美精品videosex极品1| 亚洲成人第一网站| 国产在线看一区| 精品国产一区二区三区四区vr| 国产在线视频你懂得| 亚洲女女做受ⅹxx高潮| 久久精品国产精品亚洲色婷婷| 国产原创一区| 亚洲福利小视频| 免费91在线观看| 亚洲区一区二| 国产一区二区丝袜| 亚洲人午夜射精精品日韩| 中文文精品字幕一区二区| 精品成在人线av无码免费看| 不卡亚洲精品| 亚洲二区在线播放视频| 国产成人av免费在线观看| 一本色道88久久加勒比精品| 成人福利网站在线观看| 三级做a全过程在线观看| 亚洲欧美视频在线观看视频| 午夜肉伦伦影院| 亚洲国产aⅴ精品一区二区| 亚洲欧洲日本专区| 久久久久久久福利| 另类成人小视频在线| 久久综合婷婷综合| 女子免费在线观看视频www| 在线观看亚洲精品视频| 亚洲av网址在线| 韩国精品一区二区三区| 国产人妖伪娘一区91| 青青久草在线| 午夜精品久久久久久久久久 | 少妇无码av无码专区在线观看| 未满十八勿进黄网站一区不卡| 日韩激情在线视频| 久久婷婷国产麻豆91| 精品一区二区三区在线视频| 欧洲亚洲一区二区三区四区五区| 爱情岛亚洲播放路线| 欧美一区二区三区思思人| 亚洲高潮女人毛茸茸| 天堂资源在线中文精品| 久久99精品久久久久久久青青日本| 2024短剧网剧在线观看| 欧美丰满少妇xxxbbb| 亚洲黄色网址大全| 丝袜美腿亚洲综合| 欧美日韩一区综合| 性欧美又大又长又硬| 欧美精品一区二区三区视频| 青青操国产视频| 国产一区二三区好的| 中国成人在线视频| 日韩有码欧美| 久久夜色精品国产| 国产免费一区二区三区最新不卡| 国产精品久久久久久久久快鸭| 九九视频精品在线观看| 国产成人高清| 国产精品福利在线观看| 春暖花开成人亚洲区| 欧美性感一区二区三区| 影音先锋男人在线| 蜜桃av一区二区| 永久久久久久| 91成人精品观看| 欧美xxxx做受欧美| 亚洲va久久久噜噜噜无码久久| 夜夜嗨av一区二区三区中文字幕| av在线天堂网| 国产午夜精品一区二区三区欧美| 欧美国产视频在线观看| 久久xxx视频| 久久久国产精品一区| 999久久久久| 亚洲一区二区三区中文字幕在线| 精品人妻一区二区三区日产| 欧美综合国产| 亚洲精品久久久久久一区二区| 婷婷激情成人| 国产+人+亚洲| 成人精品一区二区三区免费| 7777精品伊人久久久大香线蕉 | 噜噜噜在线视频| 久久一综合视频| 宅男在线精品国产免费观看| 97久久综合精品久久久综合| 日韩av不卡在线| 色影院视频在线| 亚洲第一色在线| 亚洲毛片一区二区三区| 亚洲日本在线天堂| 视频免费在线观看| 日本aⅴ免费视频一区二区三区 | 884aa四虎影成人精品一区| 激情视频在线播放| 久久久久久电影| 成人免费黄色av| 香蕉视频成人在线观看| 日本三级福利片| 老司机精品在线| 国产日韩在线精品av| av影片在线| 中日韩美女免费视频网站在线观看| 精品国产伦一区二区三区| 日韩欧美亚洲成人| 亚洲熟女www一区二区三区| 91丨porny丨在线| 中国黄色片一级| 亚洲一区二区伦理| 日本精品福利视频| av亚洲免费| 国产一区二区在线网站| av国产精品| 国产99久久精品一区二区| 调教一区二区| 日韩中文字幕不卡视频| 色婷婷av一区二区三| 制服视频三区第一页精品| 久久久久久亚洲av无码专区| 亚洲自拍偷拍综合| 日韩av网站在线播放| 久久婷婷国产综合国色天香| 蜜臀aⅴ国产精品久久久国产老师| 人人爽香蕉精品| 成人免费在线小视频| 午夜国产精品视频| 日韩影片在线播放| 四虎5151久久欧美毛片| 成人欧美一区二区| 国产精品亚洲综合在线观看| 国产精品国产三级国产专播精品人| 96av在线| 欧美日本国产在线| 九色porny丨首页在线| 亚洲最新av在线| 蝌蚪视频在线播放| 日韩精品欧美国产精品忘忧草| 国产精品羞羞答答在线| 欧美日韩一区视频| 亚洲婷婷久久综合| 色噜噜狠狠色综合中国| 岛国av中文字幕| 欧美视频免费在线| 中文字幕在线观看视频网站| 亚洲成人av电影在线| 久久免费小视频| 亚洲国产精品久久人人爱蜜臀| 成年人av电影| 一区二区三区国产精品| 欧美精品xxxxx| 亚洲综合一区在线| 久久久精品99| 亚洲综合男人的天堂| 久久久久久久黄色| 亚洲一区二区三区四区在线观看| 欧美日韩激情在线观看| 亚洲最新视频在线观看| 久热精品在线观看| 亚洲一区二区视频在线| 欧美日韩精品区| 欧美视频在线观看免费| 天天干天天干天天操| 精品久久久久久亚洲国产300| 丰满少妇乱子伦精品看片| 欧美日韩在线第一页| 99精品在线播放| 日本高清不卡视频| 亚洲图片小说视频| 91精品在线免费观看| www.狠狠干| 亚洲精品国产精品久久清纯直播 | 亚洲2区在线| 国产在线精品二区| 尤物tv在线精品| 亚洲日本欧美在线| 欧美成人tv| 欧美 日韩 激情| 日韩电影在线一区二区三区| www.色欧美| 国产白丝网站精品污在线入口| 国产女人18毛片水真多18| 2022国产精品视频| 五月天免费网站| 一区二区免费看| 老熟妇仑乱一区二区av| 欧美绝品在线观看成人午夜影视| 性色av蜜臀av| 亚洲精选在线观看| 麻豆网在线观看| 51色欧美片视频在线观看| 国产极品久久久久久久久波多结野| 亚洲综合在线小说| 亚洲精品小区久久久久久| 亚洲自拍的二区三区| 亚洲视频一二| 国产视频手机在线播放| 国产成人啪午夜精品网站男同| 强伦人妻一区二区三区| 亚洲天堂网中文字| 久久久久99精品成人片我成大片| 欧美一区二区三区日韩视频| 欧美69xxxxx| 欧美成人午夜剧场免费观看| a欧美人片人妖| 亚洲综合精品伊人久久| 欧美人妖在线| 精品一二三四五区| 蜜桃视频在线一区| 亚洲成人av免费在线观看| 国产精品国产自产拍在线| 久久不卡免费视频| 欧美一级高清片在线观看| 邻家有女韩剧在线观看国语| 欧美高清自拍一区| 国产精品麻豆成人av电影艾秋| 国产综合av一区二区三区| 国产精品久久久久久久免费观看| 欧美极品欧美精品欧美| 国产乱码字幕精品高清av| 国产精品情侣呻吟对白视频| 亚洲444eee在线观看| 国产精品自拍电影| 正在播放亚洲1区| 中文字幕乱码中文乱码51精品| av蓝导航精品导航| 久久久久蜜桃| 日本成人中文字幕在线| 99精品视频在线免费观看| 欧美成人片在线观看| 欧美精品一级二级| avtt亚洲| 国产成人精品一区二区三区| 日韩精品免费一区二区夜夜嗨 | 亚洲国产精品高清久久久| 超碰在线无需免费| 成人午夜高潮视频| 91久久国产| www.se五月| 中文字幕一区二区三区色视频| 国产女优在线播放| 国产亚洲精品va在线观看| 中文日产幕无线码一区二区| 久久福利电影| 久久成人一区| 极品人妻一区二区三区| 午夜亚洲福利老司机| 天堂网在线观看视频| 性欧美长视频免费观看不卡| 成人偷拍自拍| 日韩中字在线观看| eeuss鲁片一区二区三区在线观看| 久草视频在线资源| 精品国产一区二区精华| 丁香花在线观看完整版电影| 国产经品一区二区| 精品动漫3d一区二区三区免费| 国产精品熟妇一区二区三区四区 | 粉嫩精品导航导航| 国产精品一线二线三线| kk眼镜猥琐国模调教系列一区二区| 久久久久久天堂| 亚洲精品国偷自产在线99热| av色在线观看| 九九九九九精品| 丝袜亚洲另类欧美综合| 亚洲色图日韩精品| 69久久99精品久久久久婷婷| 怡红院在线观看| 精品久久蜜桃| 日韩电影在线观看电影| 亚洲精品国产精品乱码在线观看| 日韩一区二区三区视频在线| 国产嫩草在线视频| 美女一区视频| 美女视频黄 久久| 日本aⅴ在线观看| 亚洲第一网站免费视频| 国产不卡网站| 在线观看欧美一区| 国产不卡一区视频| 六月丁香激情综合| www.午夜精品| 黄色欧美网站| 香蕉视频网站入口| 亚洲免费av网站| 日韩午夜影院| 成人精品视频在线| 99精品久久久| 免费看的黄色录像| 亚洲激情 国产| 粉嫩91精品久久久久久久99蜜桃| 一二三四中文字幕| 久久久久久久久久电影| 国产99久一区二区三区a片| 欧美性在线观看| 天天射天天综合网| 久久久久成人精品无码中文字幕| 欧美色综合网站| 1234区中文字幕在线观看| 亚洲国产欧美一区二区三区不卡| 国产成人小视频| 免费在线观看av的网站| 欧美精品videosex极品1| 欧美色图国产精品| japanese在线观看| 欧美群妇大交群中文字幕| 3344国产永久在线观看视频| 制服诱惑一区| 久久九九久精品国产免费直播| www.好吊色| 成人激情免费在线| 日韩av中文字幕一区二区|