首页 > 后端开发 > C++ > 正文

为什么模板类中的静态成员初始化行为不同?

DDD
发布: 2024-10-28 08:57:02
原创
641 人浏览过

 Why Does Static Member Initialization in Templated Classes Behave Differently?

模板类中的静态成员初始化复杂性

C 中的静态成员初始化是一种广泛使用的技术,但在处理时可能会变得复杂模板化的类。在非模板化类中,可以采用嵌套辅助结构进行初始化,但当封闭类模板化时,这种方法就不够了。

考虑以下简化示例:

<code class="cpp">struct A
{
    static std::string mA;
    static InitHelper mInit;

    static const std::string& getA() { return mA; }
};
std::string A::mA;
A::InitHelper A::mInit;


template<class T>
struct B
{
    static std::string mB;
    static InitHelper mInit;

    static const std::string& getB() { return mB; }
    static InitHelper& getHelper() { return mInit; }
};
template<class T>
std::string B<T>::mB;
template<class T>
typename B<T>::InitHelper B<T>::mInit;

int main()
{
    std::cout << "A = " << A::getA() << std::endl;

    // Comment/uncomment lines to observe different behaviors
    // std::cout << "B = " << B<int>::getB() << std::endl; // [1]
    // B<int>::getHelper(); // [2]
}</code>
登录后复制

预期行为:

当 [1] 被取消注释并且 [2] 被注释时,我们期望 B::mB 被初始化为“Hello, I'm B”。 。然而,这种情况不会发生。

实际行为:

  • 用[1]和[2]评论:没有副作用
  • [1] 未注释: B::getB() 返回一个空字符串。
  • [1] 和 [2 ] 未注释: B::mB 已正确初始化。
  • 注释 [1] 且未注释 [2]: 静态初始化期间发生分段错误。

差异的原因:

根据 ISO/IEC C 2003 标准,在需要其定义的上下文中引用模板成员时,会隐式实例化模板成员。存在。但是,静态数据成员初始化(以及任何相关的副作用)仅在显式使用静态数据成员时发生。这意味着,如果模板成员仅在未实例化的模板中或在不需要其完全实例化的其他上下文中引用,则其静态数据成员将不会被初始化。

在示例中,B:: getB() 要求 B::mB 存在,但这仅强制实例化成员模板声明,而不是其定义(包括初始值设定项)。相反,B::getHelper() 确实需要 B::mInit 的定义,因为它返回对其的引用。

解决方案:

该标准禁止显式专用类模板静态数据成员的定义进行有序初始化,而其他类模板静态数据成员进行无序初始化。为了确保一致的初始化顺序,必须使用显式特化。

以上是为什么模板类中的静态成员初始化行为不同?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!