自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

全局變量:一個讓千萬程序員崩潰的致命錯誤

開發(fā)
全局變量就像是編程界的"外賣",看著特別方便,隨叫隨到,但吃多了絕對會鬧肚子!

嘿,小伙伴們! 今天我們來聊一個超級"誘人"但又特別"危險"的編程套路 —— 全局變量!

它就像是編程界的"外賣":

  • 看著特別方便
  • 隨叫隨到
  • 但吃多了絕對會鬧肚子!

全局變量的"七宗罪"

來看看這個讓人頭禿的例子:

int userCount = 0;  // 這個變量就像個沒人管的熊孩子 ??
void addUser() { userCount++; }    // 誰都能來摸一把
void removeUser() { userCount--; }  // 誰動了我的數(shù)字?!

這代碼有多可怕? 

  • 依賴全靠"緣分" - 誰用了都不知道
  • 狀態(tài)像"過山車" - 想改就改,完全沒規(guī)矩
  • 多線程直接變"蹦迪現(xiàn)場" 

拯救方案: 馴服野生變量!

想要管住調(diào)皮的全局變量,我們需要給它請個"保姆"! 

先看看這個小可愛:

class UserManager {  
    private:
        int userCount = 0;  // 乖乖呆在小籠子里 ??
};

給它加上一些規(guī)矩:

public:
    void addUser() { 
        userCount++;  // 想動手先舉手! ??♂?
    }

再來個安全門禁:

    int getCount() const { 
        return userCount;  // 只能看,不能摸! ??
    }

這樣一來:

  • 數(shù)據(jù)乖乖待在私有區(qū)域
  • 想改變需要通過正門
  • 外面的人只能隔著玻璃看 

就像把野生小動物送進了動物園,既保護了它,也保護了其他人! 

記住: 馴服野生變量的第一步,就是給它一個溫暖的家! 

這比直接把變量扔在大街上要安全多啦! 

生動有趣! 

全局變量的正確打開方式

嘿,想知道什么時候能用全局變量嗎? 來看看這些"合法"的使用場景! 

首先是這位"常量天使" :

const int MAX_USERS = 1000;    // 乖乖不變的小寶貝 ??
const double PI = 3.14159;     // 這個數(shù)字穩(wěn)如老狗! ??

為啥它們這么乖? 因為戴上了const這頂"緊箍帽",誰都別想動它們一根毛! 

再來看看"單身貴族"單例模式,獨一無二的存在 

class Logger {
private:
    Logger() = default;  // 悄悄把構(gòu)造函數(shù)藏起來 ?? - 外面的人別想new我!
    Logger(const Logger&) = delete;  // 禁止復制 ??? - 獨一無二的存在
    Logger& operator=(const Logger&) = delete;  // 禁止賦值 ??? - 不許假冒偽劣!

public:
    static Logger& getInstance() {
        static Logger instance;  // 江湖只此一家,別無分店! ??
                                // 第一次調(diào)用才會創(chuàng)建 ??
                                // C++11保證線程安全 ??
        return instance;  // 永遠返回同一個實例 ??
    }

    // 其他成員函數(shù)... ???
};

它就像是皇帝一樣,整個程序只能有一個! 想見它?必須通過getInstance()這個"御前大臣"!

最后是配置文件小管家:

namespace Config {
    const std::string APP_NAME = "超級無敵小火箭";  // 名字要起得帥氣點! ??
    const int VERSION = 42;     // 這個數(shù)字充滿智慧! ??
}

把它們放在namespace里,就像給小朋友們一個溫暖的家! 

記住這個鐵律哦:

全局變量就像辣條:

  • 偶爾吃一點點沒問題
  • 但要是貪吃,絕對會鬧肚子! 
  • 能不吃最好不吃! 

如果你突然想用全局變量,不妨先去喝杯奶茶冷靜一下! ?? 等喝完了再決定要不要用它! 

告別全局變量的絕招

嘿,想知道怎么優(yōu)雅地跟全局變量說拜拜嗎? 來看看這些法寶! 

第一招: 依賴注入大法 

class Service {
    Database& db_;  // 把數(shù)據(jù)庫抱得緊緊的~ ??
                    // 使用引用避免拷貝開銷 ??
                    // 保證數(shù)據(jù)庫對象生命周期 ?
public:
    Service(Database& db) : db_(db) {
        // 通過構(gòu)造函數(shù)注入依賴 ??
        // 比全局變量更容易測試和維護 ?
        // 明確表達了類的依賴關(guān)系 ??
    } 
};

就像點外賣一樣,想要啥直接送到家! ?? 不用自己到處找找找~

第二招: 全家福合照

struct Context {
    // ?? 這是所有重要組件的"豪華大宅"
    // ?? 通過一個對象統(tǒng)一管理所有依賴
    // ?? 避免全局變量到處飛
    
    Config config;   // ?? 配置管家,保管所有設(shè)置
    Logger logger;   // ?? 記錄小助手,負責寫日記
    Database db;     // ?? 數(shù)據(jù)管家,安全存儲數(shù)據(jù)
    
    // ?? 好處都在這:
    // ? 依賴關(guān)系一目了然
    // ?? 生命周期統(tǒng)一管理 
    // ?? 測試替換超輕松
};

瞧,多溫馨啊! 所有重要的東西都在一個相框里

第三招: 玩具工廠模式

class DatabaseFactory {
    // ?? 數(shù)據(jù)庫生產(chǎn)車間,專門制造數(shù)據(jù)庫實例
    // ?? 目的是集中管理數(shù)據(jù)庫的創(chuàng)建邏輯
    // ?? static 方法確保不需要實例化工廠類
    static Database create() {
        // ?? "localhost" 表示連接本地數(shù)據(jù)庫
        // ?? 3306 是 MySQL 的默認端口號
        // ?? 每次調(diào)用都返回全新的數(shù)據(jù)庫連接
        // ?? 避免了全局變量帶來的各種問題
        return Database{"localhost", 3306}; 
    }
};

想要新玩具? 工廠分分鐘造一個! 干凈又衛(wèi)生~

記住這個魔法口訣:

  • 全局變量就像熊孩子,到處惹事! 
  • 依賴注入像保姆,照顧得妥妥的! 
  • 工廠模式像玩具店,要啥有啥! 

最后的小提示:

  • 能傳參就傳參,別偷懶! 
  • 想用全局先冷靜,喝口奶茶! 
  • 代碼整潔最重要,保持優(yōu)雅! 

這樣的代碼,不僅程序員喜歡,產(chǎn)品經(jīng)理也開心! 因為bug少了,加班也少啦! 

全局變量的初始化小把戲

看看這群不聽話的小家伙:

// ?? 這是一個危險的全局變量初始化示例
Logger g_logger;    // ?? 急著想當?shù)谝幻腖ogger
                   // ?? 初始化順序完全不確定
                   // ?? 可能導致嚴重的依賴問題

Config g_config;    // ??♀? 和Logger搶著初始化
                   // ?? 誰先誰后全靠運氣
                   // ?? 依賴Config的代碼可能會崩潰

Database g_db;      // ??♂? 最后一個不代表最安全
                   // ?? 如果其他變量依賴數(shù)據(jù)庫
                   // ?? 可能會引發(fā)災難性后果

這就像是幼兒園搶玩具,誰先初始化完全靠運氣啦! 

與其讓它們打架,不如這樣:

Logger& getLogger() {
    // ?? 這是一個懶漢式單例模式的實現(xiàn)
    // ??? static 保證 Logger 只會在第一次調(diào)用時才會被初始化
    // ?? C++11 之后保證這種初始化是線程安全的
    // ?? 不用的時候不會占用內(nèi)存資源
    // ?? 返回引用避免了不必要的拷貝
    // ?? 后續(xù)每次調(diào)用都返回同一個實例
    static Logger log;  // 困了就睡,要用就醒~ ??
    return log;
}

這就像個小懶蟲,需要的時候才伸個懶腰起床! 

為什么這樣更好? 

  • 用到才初始化,節(jié)省資源 
  • 初始化順序明確,不會打架 
  • 線程安全有保障,放心用 

來看看實戰(zhàn)示例:

// 壞孩子版本 ?
extern Database g_db;  // 到處亂跑的熊孩子 ??
                      // 誰都可以隨意修改它 ??
                      // 多線程訪問會出問題 ??
                      // 初始化順序不確定 ??
                      // 測試時難以替換 ??

// 好孩子版本 ?
Database& getDB() {
    static Database db;  // 乖乖待在家里 ??
                        // 懶漢式單例模式 ??
                        // 用到才初始化,節(jié)省資源 ??
                        // C++11保證線程安全 ??
                        // 返回引用避免拷貝 ??
                        // 始終是同一個實例 ??
    return db;
}

記住: 與其讓變量們在初始化時打群架,不如讓它們按需登場! 

多線程下的全局變量那些事兒

嘿,小伙伴們! 今天來聊聊全局變量在多線程環(huán)境下有多"社死"! 

先看看這個"社恐"寶寶:

std::vector<User> g_users;  // 裸奔的小可憐 ??

這就像個無人管理的"公共廁所" :

  • 線程A: 我要進去! 
  • 線程B: 等等,我也要! 
  • 線程C: 借過借過! 結(jié)果? 當然是撞個滿懷啦! 

來看看這個"乖寶寶"版本:

class UserManager {
    std::mutex mutex_;      // 門衛(wèi)大爺駕到! ??
    std::vector<User> users_;  // 乖乖待在保護圈內(nèi) ??

有了門衛(wèi)以后:

public:
    void addUser(User u) {
        std::lock_guard<std::mutex> lock(mutex_);  // 先登記再進門 ??
        users_.push_back(std::move(u));  // 安全入住啦 ??
    }

這樣一來:

  • 想進門要先報到
  • 一次只能進一個
  • 有序排隊不擁擠

小貼士:

  • 全局變量就像沒人看管的熊孩子
  • mutex就是貼心小保姆
  • lock_guard就是自動門禁卡

記住: 多線程面前,全局變量不加鎖,分分鐘社死現(xiàn)場! 要么不用,要用就保護好! 

命名空間 - 變量的豪華別墅

來看看這些可憐的"流浪變量":

int count;      // 無家可歸的小可憐 ??
void reset();   // 漂泊的孤獨靈魂 ??

給它們一個溫馨小窩:

namespace GameEngine {    // 歡迎來到游戲城堡! ??
    int playerScore;     // 我是分數(shù)管家 ??
}

想要更多私密空間? 來個套娃! 

namespace Game {
    namespace Core {     // 我是豪華套房~ ??
        int secretData;  // 私密數(shù)據(jù)躲這里 ??
    }
}

現(xiàn)代C++還能這樣玩:

namespace Game::Utils {   // 無需套娃的新潮寫法 ?
    int helperCount;     // 整潔又時髦! ??
}

使用小技巧:

  • using namespace 要慎用,就像把門鑰匙到處亂扔! 
  • 命名要有意義,不要整些"黑話" 
  • 層級別太深,自己都會迷路! 

記住: 給變量一個家,比讓它流浪好一萬倍! 

單元測試小魔法

嘿,看看這個讓測試工程師抓狂的代碼:

Database g_db;  // 這個全局變量就像個頑固的老頑固 ??
void processUser() {
    g_db.query();  // 死活不讓人換掉,氣死測試工程師啦! ??
}

咱們來個華麗大變身:

class UserProcessor {
    Database& db_;  // 這個小可愛隨時可以換衣服! ??

瞧瞧這個構(gòu)造函數(shù),多么優(yōu)雅:

public:
    UserProcessor(Database& db) : db_(db) {}  // 想穿啥穿啥,隨你開心! ??

測試的時候就可以這樣玩:

void process() {
    db_.query();  // 測試時換成MockDB,美滋滋~ ??
}

有了這個魔法加持:

  • 測試工程師笑開花
  • 代碼質(zhì)量大提升
  • Bug們都躲著走

記住這個小咒語:

  • 依賴注入是好朋友
  • 全局變量是壞蛋蛋
  • 可測試性是王道呀

這樣的代碼,不僅測試工程師愛了,產(chǎn)品經(jīng)理也笑了! 因為bug少了,加班也少了! 

實用小貼士

(1) 看到全局變量先三問:

  • 真的需要嗎? 
  • 會不會后悔? 
  • 有更好方案嗎? 

(2) 非要用,請記得:

  • 寫清楚注釋
  • 放進命名空間
  • 保證線程安全

(3) 最后的忠告:

全局變量就像是恐怖片,一不小心就會嚇死人! 

  • 能用局部就別用全局 
  • 能用const就別用變量 
  • 代碼質(zhì)量大于開發(fā)速度 

記住: 與其事后擦屁股,不如一開始就把代碼寫好! 

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

2018-12-24 09:22:39

2011-11-24 14:20:24

Java

2020-02-22 21:51:43

程序員Microsoft SServerSQL

2021-12-04 23:01:33

程序員開發(fā)互聯(lián)網(wǎng)

2014-01-06 09:33:32

程序員管理

2020-10-05 21:13:37

程序員技能開發(fā)者

2015-06-08 10:48:39

程序員程序員自白

2011-02-14 13:05:17

PythonWeb

2020-07-10 09:55:15

程序員技能開發(fā)者

2015-06-16 10:31:36

程序員

2021-07-01 07:43:41

項目程序員代碼

2014-09-01 09:50:58

程序員

2022-05-23 07:56:58

C語言嵌入式開發(fā)

2019-11-07 15:30:00

EmacsIDE

2020-01-06 09:53:29

程序員

2015-08-24 10:07:13

程序員bug

2015-05-13 14:06:03

程序員糟糕的程序員

2010-10-18 11:39:41

程序員

2019-04-22 10:25:52

程序員技術(shù)職場

2012-04-12 14:49:31

程序員
點贊
收藏

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