Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is static const string member variable always initialized before used?

In C++, if I want to define some non-local const string which can be used in different classes, functions, files, the approaches that I know are:

  1. use define directives, e.g.

    #define STR_VALUE "some_string_value"
    
  2. const class member variable, e.g.

    class Demo {  
    public:  
      static const std::string ConstStrVal;  
    };  
    // then in cpp  
    std::string Demo::ConstStrVal = "some_string_value";  
    
  3. const class member function, e.g.

    class Demo{  
    public:  
      static const std::string GetValue(){return "some_string_value";}  
    };  
    

Now what I am not clear is, if we use the 2nd approach, is the variable ConstStrVal always initialized to "some_string_value" before it is actually used by any code in any case? Im concerned about this because of the "static initialization order fiasco". If this issue is valid, why is everybody using the 2nd approach?

Which is the best approach, 2 or 3? I know that #define directives have no respect of scope, most people don't recommend it.

Thanks!

like image 656
Hunter Avatar asked Apr 21 '12 05:04

Hunter


2 Answers

if we use the 2nd approach, is the variable ConstStrVal always initialized to "some_string_value" before it is actually used by any code in any case?

No

It depends on the value it's initialized to, and the order of initialization. ConstStrVal has a global constructor.

Consider adding another global object with a constructor:

static const std::string ConstStrVal2(ConstStrVal);

The order is not defined by the language, and ConstStrVal2's constructor may be called before ConstStrVal has been constructed.

The initialization order can vary for a number of reasons, but it's often specified by your toolchain. Altering the order of linked object files could (for example) change the order of your image's initialization and then the error would surface.

why is everybody using the 2nd approach?

many people use other approaches for very good reasons…

Which is the best approach, 2 or 3?

Number 3. You can also avoid multiple constructions like so:

class Demo {
public:  
  static const std::string& GetValue() {
    // this is constructed exactly once, when the function is first called
    static const std::string s("some_string_value");
    return s;
  }  
};  

caution: this is approach is still capable of the initialization problem seen in ConstStrVal2(ConstStrVal). however, you have more control over initialization order and it's an easier problem to solve portably when compared to objects with global constructors.

like image 66
justin Avatar answered Sep 18 '22 14:09

justin


In general, I (and many others) prefer to use functions to return values rather than variables, because functions give greater flexibility for future enhancement. Remember that most of the time spent on a successful software project is maintaining and enhancing the code, not writing it in the first place. It's hard to predict if your constant today might not be a compile time constant tomorrow. Maybe it will be read from a configuration file some day.

So I recommend approach 3 because it does what you want today and leaves more flexibility for the future.

like image 42
Old Pro Avatar answered Sep 19 '22 14:09

Old Pro