【问题标题】:Static const string won't get initialized静态常量字符串不会被初始化
【发布时间】:2010-11-30 20:59:55
【问题描述】:

我有一些静态常量字符串作为我的 C++ 类的私有成员。我知道 .h 中的声明和 .cpp 实践中的定义(和初始化)。在类构造函数中,我调用了一个使用这些静态字符串的函数。令人惊讶的是,在构造函数中,字符串保持未初始化(空字符串),这会产生问题。

有人能指出这里可能出了什么问题吗?我一直在使用这种静态常量字符串,但从未遇到过这种情况。

更新:m_data 在实用程序()中保持为空。我有一个 Test 类对象作为另一个类的私有成员。

这是我正在使用的一种代码:

// Test.h
class Test
{
public:
  Test();
private:
  void utility();

 static const std::string m_data;
};

// Test.cpp
const std::string Test::m_data = "Data";

Test::Test()
{
utility();
}

void Test::utility()
{
//use m_data here
}

【问题讨论】:

  • 如果您不费心发布任何代码,您希望有人如何帮助您找出问题所在? ESP?
  • 我的猜测是这些是std::string 对象(与const char* 相对),并且类对象处于全局范围内,并且无论出于何种原因在静态字符串之前构造 ;-) 大约我可以根据没有代码做。
  • const char*方式的区别说明:stackoverflow.com/questions/459942/…
  • 在添加代码时,您忘记从调用Test 构造函数的位置添加。
  • 你为什么不在调试器中运行你的代码,在出错的地方停止它,然后在这里发布堆栈。这是我们相信它不是静态初始化错误的唯一方法。

标签: c++ string static initialization constants


【解决方案1】:

这是你需要的吗?

class blah{
    static const string sz;
public:
    blah(){
        cout<<"blah constructor - string initialized to: "<<sz.c_str()<<endl;
    }
};

const string blah::sz("Hello, Blah!");

int _tmain(int argc, _TCHAR* argv[]){
    blah b;
    return 0;
}

程序输出blah 构造函数 - 字符串初始化为:Hello, Blah!

【讨论】:

    【解决方案2】:

    我会使用不同的方法:

    class Test
    {
    public:
        Test() : m_data( "Data" ) {}
    private:
         const std::string m_data;
    };
    

    我个人更喜欢这种“风格”,它可以消除在构造函数中初始化数据的任何问题,而这可能是为每个实例构造字符串的次要成本。

    【讨论】:

    • 谢谢帕特里克,但我希望数据是静态的,在这种情况下它不能使用初始化列表进行初始化。
    • 除非您对初始化数据所需的时间有疑问(除非您尝试过,否则您无法识别),否则使用静态 const 变量是没有意义的。 const 数据不能改变,因此不管它是否是静态的,它总是一样的。
    【解决方案3】:

    我检查了该程序并且它运行良好。您在使用什么 IDE? 这在 Windows 上对吗?

    如果我弄错了定义,你可以使用你声明成员的类本身,原因是它是一个 const static。

    【讨论】:

    • 我做了一个检查,根据 Visual Studio IDE,您是否允许在类本身中输入整数值。
    【解决方案4】:

    您的 TEST 类型的对象是全局对象吗?

    如果是这样,那么您将遇到初始化顺序问题。

    即。

    int main()
    {
        std::cout << "Main Entered" << std::endl;
        Test  t; // This should work
    }
    Test  plop; // This may not work depending
    

    解决方法是使用静态方法获取字符串:

    class Test
    {
        static std::string const& getData()
        {
            static std::string const data("PLOP");
            return data;
        }
        // STUFF
        // Remove this line
        // static const std::string m_data;
        Test::Test()
        {
            std::cout << "Test::Test()" << std::endl;
            Utility();
        }
    };
    // If "Test::Test()" is printed before "Main Entered"
    // You have a potential problem with your code.
    

    【讨论】:

    • 测试对象不是全局的,“data”是私有数据成员。
    • @AG 是用户定义的命名空间中的对象还是另一个类的静态成员?
    • @AG: getData() 是私有成员,因此不应影响您的代码。
    • @AG:如果测试对象是在由全局对象的构造函数调用的函数中创建的,则会产生相同的影响。基本上如果在进入 main 之前调用 Test::Test() 那么你会遇到问题!
    【解决方案5】:

    根据当前代码,我猜您尝试创建全局测试实例,很可能在不同的 .cpp 文件中。好像你正在击中可怕的static initialization order fiasco。简单地说:.cpp 文件中的全局/静态成员变量将按照它们定义的顺序进行初始化。不保证不同 .cpp 文件中的全局变量,您不能依赖一个文件中的 var 在另一个文件中的全局变量之前或之后初始化。

    【讨论】:

    • 感谢 sbk,但我的测试实例不是全局的。它是另一个类的私有成员。
    • 其他类是否有全局创建的实例? (重复直到找到类树的根。)
    【解决方案6】:

    你是这样定义的吗?

    class X
    {
    public:
          static string i;
    };
    string X::i = "blah"; // definition outside class declaration
    

    见:Static data members (C++ only)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多