2015-06-09 43 views
0

首先,我會盡力來形容目前的狀況:C++:什麼是定義非類靜態常量值的正確方法?

我適應我們使用一個現有的代碼庫,並在某些情況下的.h/.cpp文件包含多個類定義。我們不能改變API的現有公共接口,而無需對我們現在想避免的其他代碼部分進行重大修改。

我發現需要多個類使用的常量值(在同一個.cpp文件中和其他地方),因此無法定義爲類特定的常量。我知道這樣做的唯一方法是從任何類的外部定義常量(但仍在.cpp文件中)並根據需要引用它們。

我已經完成了這個工作,代碼編譯和鏈接,但是當我去運行代碼上的測試程序時,它會失敗,並顯示與我定義的常量值有關的錯誤。我得到這樣的印象,即代碼執行時,常量沒有被實際定義,並且代碼因此被炸燬。

我沒有很多編寫C++代碼的經驗,也不知道我是否以錯誤的方式來做這件事。我將在下面包含代碼片段,試圖說明我在做什麼。

在DateTime.cpp(目前DateTime.h定義DATE_FORMAT_REGEX什麼):

... 
#include <boost/regex.hpp> 

static const boost::regex DATE_FORMAT_REGEX("[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])(Z|([+|-]([01][0-9]|2[0-4]):[0-5][0-9]))?"); 

// Other class method implementations ... 

bool our_ns::Date::parse_string(const std::string& s) 
{ 
    // Validate string against regex. 
    bool valid = boost::regex_match(s, DATE_FORMAT_REGEX); 

    if (valid) { 
    ... 
    } 
} 

... 

的調用regex_match是什麼失敗。順便說一句,所有的類都是在頭文件的名字空間中定義的。

它會出現該常量未被初始化。我需要做些什麼來初始化這些值?根據我所描述的,有沒有更好的方法來做到這一點?

[更新:6/9/15 12:52 EDT] 實際上,我傳遞了組織中另一位開發人員目擊的信息。他在一個調試器中證實,當他到達爆炸線時,正則表達式項是空的。他還提到,當他做了一些實驗並將定義從.cpp移到.h文件時,錯誤不再發生。除此之外,我不知道事情是否正確執行。

+1

如果你要包含確切的錯誤,這將是最有幫助的。 –

+0

我不知道,如果錯誤信息會有何啓示,但在這裏它是: 斷言失敗:0 = m_pimpl.get(),文件c:\ appsrc \ boost_1_58_0 \提升\正則表達式\ V4 \ basic_regex。 hpp,行617 –

+0

我不知道這是否仍然有趣,但我基本上有完全相同的問題。事實證明,這是一種競爭條件,一個線程可以訪問DATE_FORMAT_REGEX並開始初始化它,然後另一個線程可以在初始化之前使用它。這個錯誤報告描述得很好: [link](https://svn.boost.org/trac/boost/ticket/2854) – DaveM

回答

1

正確的方法是將它們定義爲static const而不是const。這些是常量,它們不需要靜態鏈接。如果你這樣做是爲了避免全局命名空間,const變量總是隱含編譯單元範圍。

+1

我同意(+1),但它沒有解釋OP的當前運行時間故障並沒有真正解決問題。 – Elemental

+0

這是一種寵物討厭。 –

0

如果Date::parse_stringDate構造叫做和Date對象是靜態的,在不同的編譯單元初始化(C++文件),那麼它可能是相關的靜態變量初始化順序的問題。在這種情況下,變量初始化的順序沒有定義,所以Date對象可能在DATE_FORMAT_REGEX之前被初始化,並且因此在DATE_FORMAT_REGEX被初始化之前調用parse_string。您可以通過將DATE_FORMAT_REGEX移至Date類定義來解決此問題。

0

這可能是初始化順序的結果,這是人們可能遇到的一個衆所周知的問題。

它已經在諸如C++ FAQ等書籍中詳細描述了很長時間。這裏是一個快速參考:

https://isocpp.org/wiki/faq/ctors#static-init-order

基本上是沒有保證的順序靜態變量必須初始化。這會造成在第二個對象使用「第一個」的情況下可能遇到錯誤的情況,但「第一個」尚未初始化。請注意,「第一」和「第二」是可以互換的,其中問題的癥結在於此。事實上,更危險的情況是一個潛在的bug,在這種情況下,事情繼續發揮作用,直到有一天他們沒有 - 通常是由一個新的編譯器版本或一些這樣的改變引起的。

完全擺脫這種依賴關係會更好。你似乎不需要在這裏靜態。如果目標是限制變量的可見性,那麼使用匿名命名空間並將其放在任何使用之前。

相關問題