Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 类静态变量初始化的规则是什么?_C++_Static_Crtp - Fatal编程技术网

C++ 类静态变量初始化的规则是什么?

C++ 类静态变量初始化的规则是什么?,c++,static,crtp,C++,Static,Crtp,我有一些遗留代码,需要为消息添加一个新类(这与我的问题无关)。但事实证明,我需要声明一个空构造函数,以便初始化一些静态数据。未提供默认构造函数或编译器,但用户定义为空。我试图将代码简化为MWE,下面是我得到的: #include <iostream> using namespace std; struct Test { Test() {cout << "Test::Test()" << "\n";} void dummy(){} }; t

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

#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()
{
}
#包括
使用名称空间std;
结构测试
{

Test(){cout如果将
A
构造函数保留为默认值,并且从不调用它,则无需生成它,因此无需创建
Test
。如果在定义时显式默认它,则调用
A
构造函数或访问
A::Test
它将正确初始化

12.1施工人员【施工人员类别】

七, 当odr使用(3.2)创建其类类型(1.8)的对象时,或者当它在第一次声明后显式默认时,默认且未定义为已删除的默认构造函数将被隐式定义

结构A:公共消息 { A()=default;//除非实例化了,否则不会发出构造函数 A();//声明 }; A::A()=默认值;//显式默认定义 int main() { A;//实例化 A::test;//只需显式访问测试,就可以对其进行初始化,而不用考虑构造函数 }
C++14[温度仪表]/2:

除非类模板或成员模板的成员已显式实例化或显式专门化,否则当在要求成员定义存在的上下文中引用专门化时,成员的专门化将隐式实例化;特别是初始化(以及任何相关的副作用)除非静态数据成员本身的使用方式要求静态数据成员的定义存在,否则不会出现静态数据成员的定义

这清楚地表明,
Message::test
不会被初始化,除非它的使用方式要求其定义存在

程序中唯一需要定义的表达式是
Message
构造函数中的
test.dummy()
;因此,如果删除该表达式,则不能初始化
test

对于存在
test.dummy()
的情况,请注意它位于模板函数中,
消息的构造函数
。如果从未实例化此构造函数,则不会考虑
test.dummy()

正如VTT所指出的,[class.ctor]表示
A
的显式默认构造函数意味着除非使用了
A
,否则不定义构造函数


您的代码不使用
A
,因此未定义
A
的构造函数,因此没有调用基类构造函数(仅当定义了
A
的构造函数时才会发生),因此构造函数模板
消息()
未实例化,因此不需要存在
测试。

您能否更清楚地解释运行发布的代码时观察到的行为(即发布准确的输出),并解释它与您期望的有何不同?如果我为
A
提供一个空构造函数,我会看到
测试
构造函数的输出。如果我省略构造函数或声明它
默认值
,我什么都看不到。您可以通过注释/取消注释调用来检查它。嘿,我有另一半的谜题,但是这是答案。我确信构造器总是存在的——编译器至少会生成一个构造器。有了它,我可以看到构造器汇编程序只生成显式的默认定义。谢谢。令人惊讶的是拼图块是如何组合在一起的。谢谢你的详细解释。
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
}