5

I have some static const strings as private members of my C++ class. I am aware of the declaration in .h and definition (and initialization) in .cpp practice. In the class constructor I invoke a function that uses these static strings. Surprisingly when in constructor, the strings remain uninitialized (empty strings) which is creating a problem.

Can somebody point out what might be going wrong here? I work with such usage of static const strings all the time but never ran into such situations.

Update: m_data remains empty in utility(). I have a Test class object as a private member of another class.

Here is a kind of code I am using:

// 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
}
10
  • 8
    How do you expect anyone to help you find out what's wrong if you don't bother to post any code? ESP? Commented Sep 23, 2009 at 18:51
  • 3
    My guess is that these are std::string objects (as apposed to const char*) and the class object is at global scope and for whatever reasons gets constructed before static strings ;-) About as much as I can do based on no code. Commented Sep 23, 2009 at 18:57
  • 1
    Explanation of the difference to const char* way: stackoverflow.com/questions/459942/… Commented Sep 23, 2009 at 19:22
  • 2
    While you added the code, you forgot to add from where you call the Test constructor. Commented Sep 23, 2009 at 19:30
  • 1
    Why don't you run your code in the debugger, stop it at the point where the error occurs, and then post the stack here. That's the only way we're going to believe that it's not a static initialisation bug. Commented Sep 23, 2009 at 20:43

6 Answers 6

5

Is your object of type TEST a global?

If so you are then running into the problem with initialization order.

ie.

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

The solution is to use a static method to get the string:

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.
Sign up to request clarification or add additional context in comments.

4 Comments

Test object is not global and "data" is a private data member.
@AG is it an object in a user defined namespace or a static member of another class?
@AG: getData() is a private member so should not affect your code.
@AG: If the test object is created in a function that is called by the constructor of an object that is global will have the same affect. Basically if the Test::Test() is called before main is entered then you will gave a problem!
4

Are you defining it as such?

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

See: Static data members (C++ only)

Comments

3

Based on current code I'd guess you try to create global Test instance, most probably in a different .cpp file. Seems like you are hitting the dreadful static initialization order fiasco. Simply put: the global/static-member variables in a .cpp file will be initialized in the order they are defined. No guarantees are made about global variables in different .cpp files, you cannot rely on var in one file being initialized before or after global variable in another.

2 Comments

Thanks sbk but my Test instance isn't global. It is a private member of another class.
Does that other class have an instance created globally? (Repeat until you hit the root of the class tree.)
1

Is this what you need?

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;
}

Program Output: blah constructor - string initialized to: Hello, Blah!

Comments

0

I mase a check of the program anbd it worked fine. In what IDE are you working with ? This on windows right ?

You can use if I am mistaken make the definition if the class itself where you declare the member, the reason cause it is a const static.

1 Comment

I made a check you are allow to enter in the class itself the value onlt on integral values, according to the visual studio IDE.
0

I'd use a different approach:

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

I personally prefer this 'style' and it would remove any issues with having initialised data in the constructor at what is likely to be the minor cost of constructing the string for each instance.

2 Comments

Thanks Patrick but I wanted the data to be static in which case it cant be initialized using an initializer list.
there is no point in having a static const variable unless you have a problem with the time it takes to initialise the data (which you can't identify until you've tried it). const data cannot change therefore it does not matter if it is static or not, it will always be the same.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.