C ++静态const和初始化(有惨败) [英] C++ static const and initialization (is there a fiasco)

查看:93
本文介绍了C ++静态const和初始化(有惨败)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经很久没有回到C ++了,我对众所周知的静态初始化问题的理解有些绊脚石。

I am returning to C++ after a long absence and I am stumbling a little over my understanding of the fairly well known static initialization problem.

让我们说一个简单的Vector2类,如下所示(请注意,我知道x和y应该对getter和setter私有,对于这些,它们已经被省略了)简短):

Let's say I have a simple class Vector2 as given below (note that I am aware that x and y should be private with getters and setters, these have just been omitted for brevity):

class Vector2 {

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

现在,如果我想指定一个静态const成员来表示一个Vector2 x和y设置为1,我不确定如何继续进行操作-静态const成员是否会因为静态初始化问题而犯规,或者使它们成为const的行为意味着它们还可以吗?我正在尝试以下可能性:

Now, if I want to specify a static const member to represent a Vector2 with x and y set to 1, I am unsure on how to proceed - will static const members fall foul of the static initialization problem or will the act of making them const mean they are ok? I am toying with the following possibilities:

可能性1:

// .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;
}

可能性3:

// .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;
}

现在,我的首选写法是可能性2,因为这对我来说是一种更舒适的语法。但是,如果我从另一个类中的另一个静态方法调用getOne()方法,我会冒着崩溃和燃烧的危险吗?就像我说的那样,是因为我使用的是静态const而不是普通静态,所以我问这个问题,因为我在普通静态类成员问题上发现了很多,但在常量静态问题上却发现了很多。

Now, my preferred way to write this would be as in possibility 2, just because it is a more comfortable syntax for me. However, if I call the getOne() method from another static method in another class am I going to risk crashing and burning? As I say, it is because I am using a static const rather than a plain static that I am asking this question as I have found much on plain static class member issues, but nothing on const static issues.

我怀疑我使用静态const并不会获得任何收益,因此为了安全起见,我需要使用Possibility 3,但是我只是想问一问

I suspect that I gain nothing by the fact that I am using static const and will need to go with Possibility 3 to be safe, but I just want to ask in case someone can shed some light on this for me.

我意识到我可能正在打开自己的链接,这些链接指向的正是我所要询问的内容,但我一直在寻找

I realise I am probably opening myself up to a slew of links pointing to exactly what I am asking, but I have looked and not found before posting this.

我们将不胜感激。

推荐答案

所有它们,除了可能性 3 之外,都遭受静态初始化顺序的惨败。这是因为您的课程不是POD。在C ++ 0x中,可以通过将构造函数标记为 constexpr 来解决此问题,但是在C ++ 03中则没有这样的解决方案。

All of them, except possibility 3, suffer from the static initialization order fiasco. This is because your class is not a POD. In C++0x, this problem can be solved by marking the constructor constexpr, but in C++03 there is no such solution.

您可以删除构造函数以解决C ++ 03中的问题,然后使用

You can remove the constructor to solve the problem in C++03, and initialize using

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

这正在初始化POD,并且列表中的所有初始化程序都是常量表达式(出于静态目的初始化)。它们的初始化发生在运行任何可能在初始化之前访问它的代码之前。

This is initializing a POD, and all initializers in the list are constant expression (for the purpose of static initialization). The intialization of them happen before any code is run that might access it before being initialized.

3.6.2


具有静态存储持续时间(3.7.1)的对象应在进行任何其他初始化之前进行零初始化(8.5)。零初始化和带有常量表达式的初始化统称为静态初始化;所有其他初始化是动态初始化。在使用动态表达式初始化之前,应使用常量表达式(5.19)初始化具有静态存储持续时间的POD类型(3.9)的对象。

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


使用括号括起来的initializer-list初始化具有静态存储持续时间的聚合时,如果所有成员初始值设定项表达式均为常量表达式,且该聚合为POD类型,初始化应在初始化的静态阶段(3.6.2)进行;否则,不确定具有常量表达式的成员的初始化是在初始化的静态阶段还是在动态阶段进行。

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 ++静态const和初始化(有惨败)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆