类静态变量初始化的规则是什么? [英] What are rules for a class static variable initialization?

查看:36
本文介绍了类静态变量初始化的规则是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些遗留代码,我需要为消息添加一个新类(这与我的问题无关).但事实证明,我需要声明一个空的构造函数才能初始化一些静态.不是默认构造函数或编译器提供的,而是用户定义的空.我试图将代码减少到 MWE,我得到了:

I have some legacy code and I need to add a new class for the message (which is irrelevant to my question). But it turns out that I need to declare an empty constructor in order for some static to be initialized. Not a default constructor or compiler-provided, but empty user-defined. I tried to reduce the code to MWE and here what I get:

#include <iostream>

using namespace std;

struct Test
{
    Test() {cout << "Test::Test()" << "\n";}
    void dummy(){}
};

template<typename T>
struct Message
{
    Message()
    {
        test.dummy(); // this call have to be here in order to initialize Test, but why?
    }

    static Test test;
};

template<typename T>
Test Message<T>::test;

struct A : public Message<A>
{
    //A(){} // uncomment this (and comment the default one) to call the Test constructor
    A() = default;
};

int main()
{
}

事情是这样的:

  • 程序本身是空的,即没有创建任何实例.
  • A 类有一个 CRTP,这对示例来说似乎很关键.
  • A 的基类有一个静态声明,我希望调用它的构造函数.
  • 有一个对函数的虚拟调用,它什么也不做,但也很关键.
  • The program itself is empty, i.e. no instances are created.
  • There's a CRTP for an A class, which seems to be critical to the example.
  • There's a static declaration for the base of A and I'm expecting it's constructor to be called.
  • There's a dummy call to the function that does nothing, but also critical.

问题是,如果我不提供自定义构造函数,则永远不会调用静态构造函数.我不明白为什么我需要这个?默认或编译器生成有什么区别?为什么我需要调用一个虚拟函数?

The problem is that if I don't provide a custom constructor then the static constructor never gets called. And I can't understand why do I need this? What's the difference with defaulted or compiler generated? And why do I need to call a dummy function?

我相信这是有规律可循的.我用不同版本的 gcc 和 clang 检查了它 - 行为是相同的.我非常感谢标准/文档的链接.

I believe there's a rule for that. I checked it with different versions of gcc and clang - the behavior is the same. I very appreciate links to the standard/documentation.

推荐答案

如果你让 A 构造函数保持默认并且从不调用它,那么就不需要生成它,因此不需要创建 测试.如果您在定义时明确默认它,调用 A 构造函数或访问 A::test 它将被正确初始化.

If you leave A constructor defaulted and never call it then there is no need to generate it and therefore no need to create test. If you explicitly default it at definition, call A constructor or access A::test it will be initialized properly.

12.1 构造函数 [class.ctor]

12.1 Constructors [class.ctor]

7当 odr 使用 (3.2) 创建其类类型 (1.8) 的对象或在首次声明后显式默认时,默认且未定义为已删除的默认构造函数是隐式定义的.

7 A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used (3.2) to create an object of its class type (1.8) or when it is explicitly defaulted after its first declaration.

struct A : public Message<A>
{
    A() = default; // no constructor is emitted unless A is instantiated

    A(); // declaration
};

A::A() = default; // explicit default definition

int
main()
{
    A a; // instantiation
    A::test; // just explicitly access test so it is initialized regardless of A constructor
}

这篇关于类静态变量初始化的规则是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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