考虑下面的示例代码:
template<class D>
char register_(){
return D::get_dummy(); // static function
}
template<class D>
struct Foo{
static char const dummy;
};
template<class D>
char const Foo<D>::dummy = register_<D>();
struct Bar
: Foo<Bar>
{
static char const get_dummy() { return 42; }
};
(也可在Ideone上查看。)
我本以为只要有一个具体实例化的Foo
,比如Bar
,dummy
就会被初始化。但是这个问题(以及结尾处的标准引用)解释得很清楚,为什么这不会发生。
[...] 特别是,静态数据成员的初始化(及其相关副作用)只有在静态数据成员被使用需要存在静态数据成员的定义的方式时才会发生。
是否有任何方法可以强制dummy
被初始化(有效地调用register_
),而不需要任何Bar
或Foo
的实例(没有实例,所以没有构造函数),并且Foo
的用户不需要以某种方式明确声明该成员?对于无需派生类进行任何操作的方法来说,额外的赞赏加饼干。
编辑:找到了一种方法,对派生类的影响最小:
struct Bar
: Foo<Bar>
{ // vvvvvvvvvvvv
static char const get_dummy() { (void)dummy; return 42; }
};
虽然,我仍希望派生类不必这样做。 :|
Foo
本身中。 :/ - Xeoget_dummy
中的“dummy”是未初始化的,但这并不重要。 :) 我实际上也不使用它。 - XeoFoo<Bar> ::dummy
被初始化?而且,什么可以防止编译器优化语句(void)dummy;
(没有效果)呢? - Serge Dundichdummy
被初始化,因为它被引用了。关于优化,我需要检查一下。 - Xeoget_dummy()
时才会使用它。静态成员和全局变量在main
的第一条语句之前或在与该静态成员或全局变量的模板Foo特化实例化相同的翻译单元中定义的任何对象或函数的第一次使用之前进行初始化。因此,如果您不使用从实例化模板Foo的同一翻译单元中的任何对象或函数,则完全可以不初始化Foo<Bar> :: dummy。 - Serge Dundich