2013-08-23 67 views
0

我在代碼中需要一些小的幫助函數。 爲了工作,他們需要用一些數據初始化一次。 我應該在哪裏存儲init數據?初始值通過使用(有點)全局變量與靜態函數變量?

我已經想出了兩種方法:

我創造,我設置了專門的setter函數,然後在我的輔助函數使用helper.cpp文件範圍的靜態變量。

static int _initData = 0; 

void initHelpMe(int initData) 
{ 
    _initData = initData; 
} 

void helpMe() 
{ 
    doSomethingWith(_initData); 
} 

或者我在原輔助函數中使用了一個靜態函數變量,並在其中使用了默認參數。

void helpMe(int initData = 0) 
{ 
    static int _initData = 0; 
    if (initData != 0) 
     _initData = initData; 

    doSomethingWith(_initData); 
} 

(允許asume 0是initData的有效數據範圍的外側,並且我還沒有示出的附加代碼,以確保一個錯誤,當被調用的函數的第一次沒有首先發起它被擡起。 )

這兩種方法的優缺點是什麼?還有更好的方法嗎?

我當然喜歡第二種方法,因爲它將所有的功能保留在一個地方。但是我已經知道它不是線程安全的(這不是a.t.m的問題)。

而且,爲了讓這個更有趣,雖然是C++,但這不是用於面向對象的,而是用於程序代碼。所以請不要回答提議的對象或課程。試想一下C語言的C語言。

回答

1

我會建議你換你的數據爲對象,直到我意識到,你所要求的用C++代碼是C解決方案...

您的解決方案的

兩者都有自己的利益。

第二個是我更喜歡的,假設我們只是走「看起來像/可維護性」。然而,由於額外的if(這在第一種情況中不存在),因此helpMe被稱爲MANY倍並且initData == 0存在缺點。如果doSomethingWith()足夠長的功能和/或編譯器能夠內聯helpMe(和initData是常數),這可能會也可能不會成爲問題。

當然,代碼中的東西也必須調用initHelpMe,所以它可能會變成相同的。

總結:基於隔離/封裝,優選第二個。

1

我顯然更喜歡第二!不同編譯單元中的全局靜態數據以未指定的順序進行初始化(儘管按順序依次爲一個單元)。一次函數的本地靜態數據在第一次調用時被初始化。

如果你有兩個翻譯單元A和B.初始化過程中的單元A調用單元B的功能helpMe假設初始化的順序是A,B。 第一個解決方案將將零初始化的_initData設置爲某個initData。之後,單元B的初始化將_initData重置爲零,並可能產生內存泄漏或其他傷害。

還有第三個解決方案:

void helpMe(int initData = 0) 
{ 
    static std::once_flag once; 
    static int _initData = 0; 
    std::call_once(once, [&] { 
     _initData = initData; 
    } 
    doSomethingWith(_initData); 
} 
+0

第三種解決方案僅限於C++ 11,對不對?我知道至少lambda函數是,但我不知道std :: call_once本身。 –

+0

@ Chaos_99是的,線程也是。 –

0

我強烈地感到兩種方式。

優先使用選項2進行隔離,但選項1適用於移植到C++類。我已經編碼了兩種方式。它歸結於SW架構。

讓我提供另一點。

這兩個選項都有缺陷:您還沒有限制初始化到一個事件。 「需要用一些數據初始化一次」。看起來OP的條件保證了initHelpMe(123)HelpMe(123)後跟helpMe()的正確初始化,但是不阻止/檢測次級初始化。

如果需要防止/檢測輔助,則可以使用一些附加代碼。

// Initialization 
if (_initData != 0) { 
    ; // Handle error 
} 
_initData = initData; 

我用另一個範例如下。它可能無法在您的代碼中實現,因爲它不會通過initData作爲參數,但可以神奇地可以得到它。

void helpMe(void) { 
    static int Initialized = 0; 
    if (!Initialized) { 
    Initialized = 1; 
    _initData = initData(); 
    } 
    doSomethingWith(_initData); 
} 
+0

實際執行重新初始化的選項是該代碼的一個受歡迎的功能。每次將initData作爲參數來獲取也是一種選擇,但是由於該函數在整個代碼中都被使用,所以我不得不傳遞initData。避免發生某些事情_magically_是我的理由,不要使用簡單的全局變量。 –

+0

所以代碼需要「用一些數據初始化_至少一次」。得到它了。 – chux