函数 - 局部静态Const变量初始化语义

时间:2010-04-19 10:24:02

标签: c++ metaprogramming micro-optimization generic-programming

对于那些无法深入阅读问题的人来说,问题是粗体的。

这是this问题的后续问题。它与函数中静态变量的初始化语义有关。静态变量应初始化一次,其内部状态可能会在以后更改 - 正如我(当前)在链接问题中所做的那样。但是,有问题的代码不需要该功能稍后更改变量的状态。

让我澄清一下我的立场,因为我不需要改变字符串对象的内部状态。该代码用于元编程的特征类,因此可以从const char * const ptr获益 - 因此理想情况下需要本地成本静态const变量。我有根据的猜测是,在这种情况下,所讨论的字符串将通过链接加载器最佳地放置在内存中,并且代码更安全并映射到预期的语义。

这导致了这样一个变量的语义“C ++编程语言第三版 - Stroustrup”没有任何东西(我可以找到)来说明这个问题。所有这一切都是当线程的控制流首先到达代码时,变量被初始化一次。 这让我思考,如果以下代码是明智的,如果不是,那么预期的语义是什么?

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

以下编译GCC并两次打印“yahoo”。这就是我想要的 - 但它可能不符合标准(这就是我发布这个问题的原因)。拥有两个函数可能更优雅,“SetString”和“String”,后者转发到第一个。 如果符合标准,是否有人知道在boost(或其他地方)中的模板实现?

编辑:2010年5月11日

我正在使用以下宏在我的类中生成上面提到的getter / setter来编码编译时信息。

#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);                                          \
  } 

这些宏放在类声明中。例如:

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

希望这对其他人有用。

1 个答案:

答案 0 :(得分:4)

让我们看看C ++标准的第6.7§4节(宣言声明)。

  

允许实现执行其他的早期初始化       在相同条件下具有静态存储持续时间的本地对象       允许实现静态初始化对象       在命名空间作用域中使用静态存储       否则,在第一次控制通过时初始化这样的对象       通过宣言;这样的对象被认为是初始化的       完成初始化。

所以我们有两个案例:

  1. 我们现在在使用静态本地x输入函数之前,x将具有什么值。然后允许编译器尽早初始化该值(即使在编译时)。
  2. 我们现在不会x的值仅在我们第一次输入函数时初始化它。
  3. 所以,是的,gcc所做的不仅仅是你想要的,这种行为也符合标准。