2

这些问题以粗体显示,适用于那些不想深入阅读问题的人。

这是对这个问题的跟进。它与函数中静态变量的初始化语义有关。静态变量应该初始化一次,它们的内部状态可能会在以后改变——就像我(目前)在链接问题中所做的那样。但是,有问题的代码不需要该功能稍后更改变量的状态。

让我澄清一下我的立场,因为我不需要更改字符串对象的内部状态。该代码用于元编程的特征类,因此将受益于 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 *)
};

希望这对其他人有用。

4

1 回答 1

4

让我们看一下 C++ 标准的第 6.7 节第 4 部分(声明语句)。

在允许实现在命名空间范围内静态初始化具有静态存储持续时间的对象的相同条件下,允许实现对具有静态存储持续时间的其他本地对象执行早期初始化。否则,此类对象在控件第一次通过其声明时被初始化;这样的对象在其初始化完成时被认为已初始化。

所以我们有两种情况:

  1. 我们现在在使用静态 local 输入函数之前x,将有什么值x。然后允许编译器尽可能早地初始化该值(即使在编译时)。
  2. 我们现在x不只在第一次进入函数时初始化它的值。

所以是的,gcc 所做的不仅是您想要的,而且这种行为也符合标准。

于 2010-05-10T20:52:35.577 回答