【问题标题】:Initialisation of static class member. Why constexpr?静态类成员的初始化。为什么是 constexpr?
【发布时间】:2013-10-19 14:26:32
【问题描述】:

当我想将静态指针作为类的成员时,我需要 constexpr 以使用 nullptr 进行初始化。

class Application {
    private:
        constexpr static Application* app = nullptr;
}

谁能解释我为什么需要这样做?我找不到为什么静态变量必须在编译时存在的确切原因。

【问题讨论】:

  • 你如何使用app变量?
  • 指针应该作为指向 Application 类实例的指针(分别指向从 Application 基类派生的类的实例)。我用 OpenGL 和 Freeglut 编写了一个程序,我需要“包装” Freeglut 的 c 接口(使用类成员函数进行回调注册)。

标签: c++ c++11 initialization static-members constexpr


【解决方案1】:

如果您不希望它是 constexpr(并且它不是整数),那么您需要在类主体之外对其进行初始化:

class Application
{
private:
    static Application* app;
};

Application* Application::app = nullptr;

【讨论】:

  • 感谢您的评论。我没有使用 constexpr 的偏好。我更感兴趣的问题是为什么在其他形式的类内初始化不需要这个特殊关键字时,类内初始化需要这个特殊关键字。
【解决方案2】:

那是因为你在类定义中初始化它。这仅允许用于常量整数和枚举类型(总是)和constexpr 数据成员(C++11 起)。通常,您会在定义它的位置(在类之外)对其进行初始化,如下所示:

Application.h

class Application {
    private:
        static Application* app;
}

Application.cpp

Application* Application::app = nullptr;

请注意,即使在constexpr 的情况下,您也需要提供类外定义,但它不能包含初始化程序。不过,我相信第二种情况是您真正想要的。

【讨论】:

  • 感谢您的有用评论。您在类内部编写的初始化只允许用于常量...类型。但它也可能是非常量的......类型,不是吗?
  • @Meiner A static 类数据成员只能在类中初始化,如果它是 constexpr 的文字类型或它是 const,而不是 volatile,并且是整数或枚举类型。
  • 感谢您的澄清。没有意识到您在原始评论中只谈论静态类内初始化。
  • @yau 你能澄清你的编辑建议吗? C++11 9.4.2/3 说“如果成员在程序中被 odr-used (3.2) 使用,则该成员仍应在命名空间范围内定义,并且命名空间范围定义不应包含 initializer。 i>"
  • 对于constexpr static 成员,如果不是odr-used,则不需要提供类外声明。从 C++17 开始,如果声明了静态数据成员,则隐式为 inline,不再需要在类外声明。
【解决方案3】:

静态变量不需要“在编译时就存在”。但是如果你想在类内部初始化一个静态变量,它的值需要在编译时知道。

但是,我不知道这个限制的原因。

【讨论】:

  • 我认为限制与单一定义规则有关。查看 Kindreads 链接,它更详细。
【解决方案4】:

通常,您需要在类声明之外初始化一个静态成员变量,除非它是 const。我认为this 比我解释得更好。

【讨论】:

  • 非常有趣的链接。我没有考虑 ODR。所以 constexpr 起作用的原因是隐含的 const,对吧?我只是意识到,当初始化为 constexpr 变量时,我以后无法更改静态变量。
猜你喜欢
  • 2021-08-07
  • 2016-10-15
  • 1970-01-01
  • 2012-07-16
  • 2013-01-10
  • 1970-01-01
  • 1970-01-01
  • 2011-07-18
相关资源
最近更新 更多