微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

POD 默认初始化如果是静态的和构造函数如果是自动的?

如何解决POD 默认初始化如果是静态的和构造函数如果是自动的?

在下面的示例中,Y 和 X 给出警告“变量具有静态存储持续时间和非 POD 类型”(pclint,Autosar A3-3-2)。

struct Y {int t; Y() {t = 0;}};
class X {private: int t; public: X() {t = 0;}};
struct Z {int t;};

X x; // warning: variable 'x' has 'static' storage duration and non-POD type
Y y; // variable 'y' has 'static' storage duration and non-POD type
Z z;

我有两个问题。

  1. 调用构造函数之前会发生什么来证明警告是正确的?

编辑:在我的情况下,全局变量仅在标准命名空间中使用,并且数据由该命名空间中的全局函数访问。因此应该在访问数据之前执行构造函数

  1. 如何避免 Y 和 X 出现的警告?如果与自动存储一起使用(对于 Z),我想避免可能的未初始化状态,因此我想保留构造函数或以其他方式达到目标。

一种解决方案可能是使用 C++ 包装类来初始化结构。是否有更简单/替代的解决方案,其中不会发生成员“int t”的未初始化使用?

解决方法

来自the AutoSAR C++14 Guidelines

规则 A3-3-2(必需、实施、自动化)

静态和线程局部对象应为常量初始化。

基本原理

一般来说,使用非常量全局变量和静态变量会掩盖 API 的真正依赖,因为它们可以从任何地方访问 的源代码。因此,它使代码更难 维护、可读性和可测试性明显降低。

一个特殊的问题是构造函数和 静态变量的初始值设定项仅被部分调用 由 C++ 语言标准指定,甚至可以从构建中更改 建立。这可能会导致难以发现或调试的问题。

[...]


在调用构造函数之前会发生什么来证明警告是正确的?

该规则的基本原理是避免动态初始化适用于静态初始化的复杂规则,这是一个常见的原因,例如静态初始化失败。


如何避免 Y 和 X 出现的警告?如果与自动存储一起使用(对于 Z),我想避免可能的未初始化状态,因此我想保留构造函数或以其他方式达到目标。

对您的示例的简单修复是使它们的构造函数 constexpr,这样 static 存储持续时间对象 xyconstant-initialized instead of zero-initialized 作为一部分静态初始化:

执行常量初始化而不是零初始化 静态和线程局部 (C++11 起) 对象以及在所有其他对象之前 初始化。只有以下变量是常量初始化的:

[...]

  1. 由构造函数调用初始化的类类型的静态或线程本地对象,如果构造函数是 constexpr 和所有 构造函数参数(包括隐式转换)是常量 表达式, 以及如果构造函数初始化器中的初始化器 仅列表和类成员的大括号或等号初始值设定项 包含常量表达式。

例如(通过常量表达式将 t 数据成员的初始化移动到其默认成员初始值设定项):

struct Y {
    int t{0}; 
    constexpr Y() {}
};

class X {
 private: 
    int t{0}; 
 public: 
    constexpr X() {}
};

X x;  // static initialization is constant-initialization
Y y;  // static initialization is constant-initialization

或者在 t 构造函数的成员初始值设定项列表中初始化 constexpr 成员:

struct Y {
    int t; 
    constexpr Y() : t{0} {}
};

class X {
 private: 
    int t; 
 public: 
    constexpr X() : t{0} {}
};

最后,请注意 POD 不再是 C++11 的标准术语(已弃用),并且由于 AutoSAR C++14 指南自然适用于 C++14,因此应考虑完全放弃 POD 的概念班级类型;这同样适用于 pclint。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。