2014-12-02 75 views
1

我遇到了一个常量静态字符串类成员的初始化顺序问题。有些代码:如何确保const静态成员的初始化顺序?

constants.h

class Constants 
{ 
public: 
    // not used right now 
    Constants& getInstance(); 

    const static std::string CONST_STRING; 
}; 

constants.cpp

const std::string Constants::CONST_STRING = "my string"; 

Constants& Constants::getInstance(); 
{ 
    static Constants c; 
    return c; 
} 

这是经典的常量静态初始化(忽略getInstance)。但是,如果我再尝试另一种翻译单位的其他地方使用该常数是这样的:

class OtherClass 
{ 
public: 
    OtherClass() 
    { 
     // tried uncommenting next line 
     // Constants::getInstance(); 
     std::string str(Constants::CONST_STRING); 
     std::cout << str; 
    } 
} 

OtherClass obj; // note global 

CONST_STRING是空的,即它已建成但尚未初始化。我知道整个初始化顺序不是跨翻译单元定义的,而且我猜这样的东西在这里适用?

但是,删除注释掉的行,试图确保常量是完全构造之前使用(我不相信这是必要的,但给它一个去......)仍然不能解决的问题。

问题:

  • 我如何能确保在任何人尝试使用它们常量静态成员完全初始化?
  • 这是最好的C + + 11的方法有一个类与常量关联?是constexpr东西可以在这里使用?
+3

您的常量似乎实现Singleton模式 - 你为什么不使字符串通过访问单身人士?即让你的字符串成为一个成员并在单例的构造函数中初始化它。 – BeyelerStudios 2014-12-02 17:32:16

+0

有关静态初始化命令失败的信息,请参阅[此C++ FAQ条目](http://www.parashift.com/c++-faq/static-init-order-on-first-use.html)。 – cdhowie 2014-12-02 17:34:32

+0

'getInstance()'对'CONST_STRING'的初始化没有影响。 'constexpr'不是一个选项,因为'basic_string'构造函数不是'constexpr'。如果你想确保一个特定的顺序,你可以使'CONST_STRING'函数返回一个'const&'到一个函数local'static std :: string'。 – Praetorian 2014-12-02 17:34:46

回答

1

也许这是你在寻找:

const std::string & GetConstantsString(){ 
    static const std::string CONST_STRING = "My string"; 
    return CONST_STRING; 
} 

由于@AndreyT指出,文本类型常量静态都不允许有一流的初始化,所以我选择#1将不工作

+0

我不认为选项1有效,即使它有效,它也不能解决任何问题。选项2中的返回类型应该是'std :: string const&' – Praetorian 2014-12-02 17:37:45

+0

Er ...只允许* literal类型* const静态成员拥有类内初始化程序。 'std :: string'不是一个文字类型。您的“第一选项”在语言中不存在。 – AnT 2014-12-02 17:37:49

+0

@cdhowie叶谢谢 – Quest 2014-12-02 17:40:05

1

翻译单元中全局变量的初始化将在该翻译单元内的隐藏代码中发生。您无法控制隐藏代码位将被调用的顺序。

常量与基本数据类型可以在编译时,而不是运行时被初始化,所以这会工作:

const char Constants::CONST_STRING[] = "my string";