C++ static const 和初始化(有没有惨败)

标签 c++ static initialization constants

我在久违后重返 C++,我对众所周知的静态初始化问题的理解有些磕磕绊绊。

假设我有一个简单的类 Vector2,如下所示(请注意,我知道 x 和 y 应该与 getter 和 setter 私有(private),为简洁起见,这些只是被省略了):

class Vector2 {

public:
  Vector2(float x, float y) :x(x), y(y) {};
  float x,y;
}

现在,如果我想指定一个静态常量成员来表示 x 和 y 设置为 1 的 Vector2,我不确定如何进行——静态常量成员是否会陷入静态初始化问题或让他们 const 意味着他们还好吗?我正在考虑以下可能性:

可能性一:

// .h
class Vector2 {

public:
  Vector2(float x, float y) :x(x), y(y) {}
  static const Vector2 ONE;
  float x,y;
};

// .cpp
const Vector2 Vector2::ONE = Vector2(1.f, 1.f);

可能性2:

// .h
class Vector2 {

public:
  Vector2(float x, float y) :x(x), y(y) {}
  static const Vector2& getOne();
  float x,y;
private: 
  static const Vector2 ONE;
};

// .cpp
const Vector2 Vector2::ONE = Vector2(1.f, 1.f);

static const Vector2& Vector2::getOne() {
  return ONE;
}

可能性三:

// .h
class Vector2 {

public:
  Vector2(float x, float y) :x(x), y(y) {}
  static const Vector2& getOne();
  float x,y;
};

// .cpp
const Vector2& Vector2::getOne() {
  static Vector2 one(1.f,1.f);
  return one;
}

现在,我更喜欢用第二种方式来编写它,因为它对我来说是一种更舒适的语法。但是,如果我从另一个类中的另一个静态方法调用 getOne() 方法,我是否会面临崩溃和燃烧的风险?正如我所说,这是因为我使用的是静态 const 而不是普通静态,所以我问这个问题,因为我在普通静态类成员问题上发现了很多,但在 const static 问题上却一无所获。

我怀疑我使用的是 static const 并且需要使用可能性 3 以确保安全,这一事实让我一无所获,但我只是想问一下,以防有人能为我阐明这一点。

我意识到我可能会打开大量指向我所问内容的链接,但在发布此之前我已经看过但没有找到。

如有任何帮助,我们将不胜感激。

最佳答案

除了可能性 3 之外,所有这些都遭受了静态初始化顺序的失败。这是因为您的类(class)不是 POD。在C++0x中,这个问题可以通过标记构造函数constexpr来解决,但是在C++03中没有这样的解决方法。

在C++03中可以去掉构造函数解决问题,使用初始化

const Vector2 Vector2::ONE = { 1.f, 1.f };

这是在初始化一个POD,列表中的所有初始化器都是常量表达式(用于静态初始化)。它们的初始化发生在运行任何可能在初始化之前访问它的代码之前。

3.6.2:

Objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other initialization takes place. Zero-initialization and initialization with a constant expression are collectively called static initialization; all other initialization is dynamic initialization. Objects of POD types (3.9) with static storage duration initialized with constant expressions (5.19) shall be initialized before any dynamic initialization takes place.

8.5.1/14:

When an aggregate with static storage duration is initialized with a brace-enclosed initializer-list, if all the member initializer expressions are constant expressions, and the aggregate is a POD type, the initialization shall be done during the static phase of initialization (3.6.2); otherwise, it is unspecified whether the initialization of members with constant expressions takes place during the static phase or during the dynamic phase of initialization.

关于C++ static const 和初始化(有没有惨败),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2373859/

相关文章:

c++ - CUDA:内存限定符的非法组合

C++:使用int vs struct对静态成员变量进行依赖初始化的静态

c++ - 当函数中静态变量的构造函数异常终止时会发生什么?

c - 嵌套数组的初始化?

java - 局部变量还没有初始化?

c++ - 在 map 中使用对 lambda 的引用作为比较器(正确的方法?)

c++ - 初始化列表: cannot convert ‘Participant’ to ‘unsigned int’ in initialization

c - 关于 "static"的用法,非常基本

java - 当类被参数化时,类的静态字段是否在测试之间共享?

c++ - 如何使用 boost.lambda 和 boost.range 从容器中进行选择?