2

The questions are in bold, for those that cannot be bothered reading a question in depth.

This is a followup to this question. It is to do with the initialization semantics of static variables in functions. Static variables should be initialized once, and their internal state might be altered later - as I (currently) do in the linked question. However, the code in question does not require the feature to change the state of the variable later.

Let me clarrify my position, since I don't require the string object's internal state to change. The code is for a trait class for meta programming, and as such would would benifit from a const char * const ptr -- thus Ideally a local cost static const variable is needed. My educated guess is that in this case the string in question will be optimally placed in memory by the link-loader, and that the code is more secure and maps to the intended semantics.

This leads to the semantics of such a variable "The C++ Programming language Third Edition -- Stroustrup" does not have anything (that I could find) to say about this matter. All that is said is that the variable is initialized once when the flow of control of the thread first reaches the code. This leads me to ponder if the following code would be sensible, and if not what are the intended semantics ?.

#include <iostream>
const char * const GetString(const char * x_in)
{
    static const char * const x = x_in;
    return x;
}

int main()
{
  const char * const temp = GetString("yahoo");
  std::cout << temp << std::endl;
  const char * const temp2 = GetString("yahoo2");
  std::cout << temp2 << std::endl;
}

The following compiles on GCC and prints "yahoo" twice. Which is what I want -- However it might not be standards compliant (which is why I post this question). It might be more elegant to have two functions, "SetString" and "String" where the latter forwards to the first. If it is standards compliant does someone know of a templates implementation in boost (or elsewhere) ?

edit: 11-may-2010

I am using the following macro to generate the above mentioned getter/setters in my classes that encode compile time information.

#define MACRO_STATIC_SETTING_PTR(name, type)                          \
  static const type const set_##name (const type const name##_in) {   \
    static const type const name = name##_in;                         \
    return name;                                                      \
  }                                                                   \
  static const type const name() {                                    \
    return set_##name(NULL);                                          \
  } 

#define MACRO_STATIC_SETTING(name, type)                              \
  static const type set_##name (const type name##_in) {               \
    static const type name = name##_in;                               \
    return name;                                                      \
  }                                                                   \
  static const type name() {                                          \
    return set_##name(NULL);                                          \
  } 

These macros are placed inside a class declaration. For example:

template<class tag>
class ConfigInstance{
public:
  MACRO_STATIC_SETTING_PTR(sqllite3_filename, char *)
};

Hopefully this will be useful to others.

7
  • In const char * const GetString, the second const is meaningless, since the qualifier applies to l-values only. Commented Apr 19, 2010 at 10:43
  • 2
    The first const means the pointer points to read only memory while the second const makes the pointer itself constant (const works on the element left besides it, except when it is the first token, then it works to the element on the right). char* GetString would generate a variable pointer to constant memory, while char* const GetString gives a constant pointer to writable memory. Commented Apr 19, 2010 at 11:18
  • Probably a typo in your example, but outputing temp twice will always give the same result. Commented Apr 19, 2010 at 11:20
  • 1
    @Rudi: what you describe is for L-values, not for function return types. A good compiler will warn you about this. Commented Apr 19, 2010 at 23:40
  • 1
    @JRL Arrgh! I mixed up x and GetString in my mind. Commented Apr 20, 2010 at 5:56

1 Answer 1

4

Let's look into part 6.7 §4 (Declaration statement) of the C++ standard.

An implementation is permitted to perform early initialization of other local objects with static storage duration under the same conditions that an implementation is permitted to statically initialize an object with static storage duration in namespace scope. Otherwise such an object is initialized the first time control passes through its declaration; such an object is considered initialized upon the completion of its initialization.

So we have two cases:

  1. Either we now before we enter the function with a static local x, what value x will have. Then the compiler is allowed to initialize the value as early as possible (even at compile time).
  2. We don't now the value of x initialize it only the first time we enter our function.

So yes what gcc does is not only what you want, this behavior is also standard compliant.

Sign up to request clarification or add additional context in comments.

1 Comment

It should be worthwile to note that when the compiler choose option 2 (initialization of xthe first time we enter the function), the function is not thread safe.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.