偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

不會吧!全局變量在 main 前的初始化,竟然是靜態(tài)、動態(tài)兩步走?

開發(fā)
全局變量的初始化是一個分為靜態(tài)初始化和動態(tài)初始化的有序過程,發(fā)生在 main 函數(shù)執(zhí)行之前。

全局變量在 main 函數(shù)前初始化,這個大家都知道,但是,全局變量的初始化方式卻是一個容易被忽視但又至關(guān)重要的細(xì)節(jié),全局變量的初始化可以分為靜態(tài)初始化和動態(tài)初始化兩種方式。

一、 什么是全局變量初始化?

全局變量是在所有函數(shù)體之外聲明的變量。

初始化是指為變量賦予其初始值的過程,它們的內(nèi)存空間在程序啟動時就會被分配,并且它們的初始化過程發(fā)生在 main 函數(shù)執(zhí)行之前。

這個初始化過程可以分為兩個不同的階段:靜態(tài)初始化 (Static Initialization) 和 動態(tài)初始化 (Dynamic Initialization)。

這里需要知道的是: static 局部變量 、static 類成員變量 和全局變量它們都是具有靜態(tài)生命周期的變量!

二、 靜態(tài)初始化:編譯鏈接時的確定性

靜態(tài)初始化是全局變量初始化的第一個階段,它發(fā)生在程序加載之前,由編譯器和鏈接器在可執(zhí)行文件中預(yù)先安排。

這個階段的特點是:

(1) 初始化值必須常量表達式

靜態(tài)初始化的值必須是在編譯時就能完全確定的常量。這包括字面量(如 10, "hello")、const 常量、枚舉值,以及由這些常量組成的算術(shù)表達式等。(C++11及后續(xù)標(biāo)準(zhǔn)中,常量初始化被明確定義為靜態(tài)初始化的一部分,用于優(yōu)化常量表達式的處理。)

(2) 零初始化:

如果全局變量(或靜態(tài)變量)沒有被顯式地初始化,編譯器會對其進行零初始化。這意味著整型變量會被初始化為 0,浮點型為 0.0,指針為 nullptr (或 NULL),布爾值為 false,聚合類型(如數(shù)組、結(jié)構(gòu)體)的每個成員都會被遞歸地零初始化。

(3) 實現(xiàn)方式:

 編譯器通常會將靜態(tài)初始化的值直接寫入可執(zhí)行文件的特定段(如 .data 段用于顯式初始化的非零值,.bss 段用于零初始化的值)。程序加載時,這些段的內(nèi)容會被直接映射到內(nèi)存中,無需執(zhí)行額外的代碼。

簡單來說,靜態(tài)初始化就像是在"設(shè)計圖紙"階段就已經(jīng)確定好的固定參數(shù),直接"印"在了最終的產(chǎn)品上。

示例:

c++復(fù)制代碼
#include
int g_zero_initialized;           // 靜態(tài)初始化:零初始化為 0
int g_explicit_static = 10;     // 靜態(tài)初始化:用常量表達式 10 初始化
const char* g_message = "Hello";  // 靜態(tài)初始化:用字符串字面量(常量)初始化
const int g_const_val = 5 * 2;    // 靜態(tài)初始化:用常量表達式初始化

int main() {
    std::cout << "g_zero_initialized: " << g_zero_initialized << std::endl; // 輸出 0
    std::cout << "g_explicit_static: " << g_explicit_static << std::endl;  // 輸出 10
    std::cout << "g_message: " << g_message << std::endl;            // 輸出 Hello
    std::cout << "g_const_val: " << g_const_val << std::endl;        // 輸出 10return 0;
}

靜態(tài)初始化的局限性在于它只能處理常量表達式(例如示例當(dāng)中的 5 * 2)。如果初始值依賴于運行時計算(如函數(shù)調(diào)用或隨機數(shù)生成),就無法使用靜態(tài)初始化,轉(zhuǎn)而需要動態(tài)初始化。

三、 動態(tài)初始化:程序啟動時的靈活性

靜態(tài)初始化只能處理常量表達式,但有時我們需要用更復(fù)雜的方式來初始化全局變量,比如調(diào)用函數(shù)、使用非 const 全局變量的值,或者初始化一個類的全局對象并調(diào)用其構(gòu)造函數(shù)。這時,動態(tài)初始化 就派上用場了。

動態(tài)初始化發(fā)生在靜態(tài)初始化完成之后,main 函數(shù)開始執(zhí)行之前。

它的特點是:

(1) 初始化值可以是非常量:

動態(tài)初始化允許使用函數(shù)調(diào)用、其他變量的值(即使它們本身是動態(tài)初始化的)或者需要運行時計算的表達式來初始化全局變量。

(2) 執(zhí)行時機:

在程序啟動過程中,靜態(tài)初始化完成后,但在 main 函數(shù)執(zhí)行前,會有一段特殊的啟動代碼(runtime startup code)負(fù)責(zé)執(zhí)行這些動態(tài)初始化操作。

(3) C++ 類對象:

全局類對象的構(gòu)造函數(shù)調(diào)用通常屬于動態(tài)初始化(除非構(gòu)造函數(shù)非常簡單且滿足特定條件,可能被優(yōu)化為靜態(tài)初始化)

簡單來說,動態(tài)初始化就像是在產(chǎn)品組裝完成后、正式使用前,進行的"開機設(shè)置"或"首次配置"。

示例:

#include <iostream>
#include <string>
#include <cmath>
#include <ctime>

// 靜態(tài)初始化(零初始化)
int g_some_value;

// 動態(tài)初始化 - 需要運行時計算
double g_pi = acos(-1.0); // acos不是常量表達式

// 動態(tài)初始化 - 需要調(diào)用函數(shù)
time_t g_start_time = time(nullptr); // time()函數(shù)調(diào)用

// 動態(tài)初始化 - 依賴其他全局變量 (可能引發(fā)順序問題)
// int g_dependent_value = g_some_value + 5; // 如果g_some_value也是動態(tài)初始化,需注意順序

// C++ 類對象的動態(tài)初始化
classMyClass {
public:
    MyClass(const std::string& name) : name_(name) {
        std::cout << "構(gòu)造函數(shù)執(zhí)行: " << name_ << std::endl;
    }
    std::string getName()const{ return name_; }
private:
    std::string name_;
};

std::string get_username(){
    // 模擬獲取用戶名
    return"默認(rèn)用戶名";
}

MyClass g_my_object(get_username()); // 調(diào)用構(gòu)造函數(shù)和get_username(),動態(tài)初始化

intmain(){
    std::cout << "main 函數(shù)開始執(zhí)行..." << std::endl;
    std::cout << "g_pi: " << g_pi << std::endl;
    std::cout << "g_start_time: " << g_start_time << std::endl;
    // std::cout << "g_dependent_value: " << g_dependent_value << std::endl;
    std::cout << "g_my_object name: " << g_my_object.getName() << std::endl;

    // 即使 g_some_value 在 main 之前被動態(tài)初始化賦值(如果它是動態(tài)的話)
    // 這里訪問它時,它已經(jīng)完成了初始化
    g_some_value = 100; // 在 main 中修改
    std::cout << "g_some_value in main: " << g_some_value << std::endl;

    return0;
}

輸出:(VS2022)

構(gòu)造函數(shù)執(zhí)行: 默認(rèn)用戶名
main 函數(shù)開始執(zhí)行...
g_pi: 3.14159
g_start_time: 1744354404
g_my_object name: 默認(rèn)用戶名
g_some_value in main: 100

四、 為什么區(qū)分靜態(tài)和動態(tài)初始化

區(qū)分這兩個階段主要是為了效率和靈活性的平衡:

  • 靜態(tài)初始化效率高: 它在編譯時確定值,程序加載時映射到內(nèi)存,不增加程序啟動時間。對于大量簡單的全局?jǐn)?shù)據(jù),這是最優(yōu)的方式。
  • 動態(tài)初始化提供靈活性: 它允許進行復(fù)雜的初始化操作,適應(yīng)更多場景,但會稍微增加程序啟動的開銷。

五、 靜態(tài)初始化順序災(zāi)難

這個概念里面的靜態(tài)指的是生命周期:靜態(tài)存儲期(指的是變量的生命周期從程序開始時分配內(nèi)存,直到程序結(jié)束時才釋放)

動態(tài)初始化的一個潛在問題是初始化順序。在不同的編譯單元(不同的 .cpp 文件)中定義的全局變量,它們的動態(tài)初始化順序在 C++ 標(biāo)準(zhǔn)中并沒有嚴(yán)格規(guī)定。如果你在一個編譯單元的動態(tài)初始化中,依賴了另一個編譯單元中需要動態(tài)初始化的全局變量,就可能因為后者的初始化尚未完成而出錯,這就是所謂的"靜態(tài)初始化順序災(zāi)難"。

避免方法:

  • 盡量使用靜態(tài)初始化: 如果可能,優(yōu)先使用常量表達式進行靜態(tài)初始化。
  • 局部靜態(tài)變量: 將全局變量改為函數(shù)內(nèi)的靜態(tài)變量,利用其首次調(diào)用時才初始化的特性來保證依賴關(guān)系。
MyClass& get_global_object() 
{
    static MyClass instance(get_username()); // 在首次調(diào)用時才進行動態(tài)初始化
    return instance;
}

六、 靜態(tài) vs 動態(tài)初始化

特性

靜態(tài)初始化

動態(tài)初始化

初始化時機

編譯時(概念上)

運行時(程序啟動時)

初始值類型

常量表達式

可能涉及函數(shù)調(diào)用或運行時計算

性能開銷

幾乎無開銷

可能有運行時開銷

適用場景

固定值,如配置參數(shù)

依賴環(huán)境或動態(tài)計算的值

潛在問題

初始化順序問題

總體來說,我覺得我們開發(fā)當(dāng)中要注意這幾點:

  • 第一盡量使用靜態(tài)初始化以提高性能并避免初始化順序問題。
  • 第二如果必須依賴運行時環(huán)境,確保初始化邏輯簡單且無依賴關(guān)系。
  • 第三對于復(fù)雜的初始化需求,可以將邏輯封裝到函數(shù)中,并在程序啟動時顯式調(diào)用。

七、 總結(jié)

  • 全局變量的初始化是一個分為靜態(tài)初始化和動態(tài)初始化的有序過程,發(fā)生在 main 函數(shù)執(zhí)行之前。
  • 靜態(tài)初始化處理常量表達式和零初始化,在編譯鏈接時確定,效率高。
  • 動態(tài)初始化處理非常量表達式、函數(shù)調(diào)用和類對象構(gòu)造,在程序啟動時執(zhí)行,靈活性強。
責(zé)任編輯:趙寧寧 來源: CppPlayer
相關(guān)推薦

2009-08-14 00:38:14

C#類庫編譯

2021-08-04 08:31:10

MySQL數(shù)據(jù)庫日志

2021-09-07 11:20:02

binlogMySQL數(shù)據(jù)庫

2010-09-10 13:34:41

2020-08-05 14:28:32

編程程序員代碼

2025-02-19 12:40:33

JWT

2009-08-31 09:47:22

C#靜態(tài)變量初始化

2022-10-28 09:51:18

PrintfLinux開發(fā)

2020-09-29 06:45:49

JDK

2021-12-06 17:44:56

MHAMySQL高可用

2015-06-18 11:04:58

2021-07-28 06:51:08

Nacos代理模式

2020-12-15 08:05:40

路由器服務(wù)器網(wǎng)絡(luò)層

2024-08-05 01:28:26

2015-10-27 13:36:52

2009-12-21 18:02:02

WCF狀態(tài)保存

2024-09-27 11:38:49

2013-07-17 16:16:06

Android全局變量定義全局變量Application

2009-07-20 16:10:31

ASP.NET頁面靜態(tài)

2010-07-13 10:52:02

點贊
收藏

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