1

在 C++ 中,普通旧数据 (POD) 局部变量默认未初始化。不过,我注意到这会导致错误,因为尝试读取未初始化变量的值是未定义的行为。

有没有办法强制编译器自动初始化所​​有局部变量?也许是一个内置了这个特性的编译器,或者一个常见编译器的编译器开关,比如 GCC 或 Clang?我可以使用 Gnu 扩展;它不必是标准的。

我希望变量是默认初始化的,这意味着 anint将设置为 0。

我厌倦了将所有 localint和私有类字段分配给 0。

4

2 回答 2

1

我知道没有开关可以做,即使它确实存在,它也只是一个“调试”功能,不能在生产代码中使用。

示例:电子围栏库具有将内存初始化为 0 或0xff

EF_FILL 当设置为 0 到 255 之间的值时,分配的内存的每个字节都被初始化为该值。这可以帮助检测未初始化内存的读取。当设置为 -1 时,一些内存用零填充(大多数系统上的操作系统默认值),一些内存将保留上次使用期间写入它的值。

(仅适用于分配的内存,不适用于自动内存)。

依赖未定义为/在标准中的开关会使您的代码不可移植。在某些时候,有人会使用您的代码在其他平台上交叉编译它,这将失败。

作为一种帮助/保护措施,像Coverity 之类的工具(注意:我不隶属于这家公司)可以检测代码中未初始化的 POD 成员。可能有免费的工具可以做同样的事情。

因此,如果有一个或 2 个 POD 成员(c++11),我会怎么做:

class Foo
{
   ...
   private:
      int x = 0;
      int y = 0;
};

如果你有无数个成员,也许可以创建一个 POD 类/结构,创建 1 个具有这种类型的成员,并使用最有效的初始化方法将其初始化为 0:

class Foo
{
   ...
   private:
      struct Pod
      {
        int x,y,z,whatever;
      };
      Pod m = {0};
};

这迫使访问成员m.x......不透明

或者(可能有点hacky但有效),创建一个POD结构,然后从中继承你的类。您现在可以memset在默认构造函数中应用 POD 结构的大小

  struct Pod
  {
    Pod()
    {
       std::memset(this,0,sizeof(Pod));
    }
    int x,y,z,whatever;
  };

  class Foo : private Pod
  {
     public:
       ...
      private:
        std::string name;
        std::vector<int> elements;
  };

sizeof(Pod)值确保memset仅将 的成员设置Pod为 0。

如果Pod来自无法更改的 C 结构,则可以memset在构造函数中移动语句Foo,保持sizeof(Pod)

于 2019-03-22T22:19:58.070 回答
0

有一个建议用零初始化局部变量编译 linux 内核,参见今年 linux.conf 的介绍https://youtu.be/FY9SbqTO5GQ?t=742

为了做到这一点,演示者团队使用了一个实验性 gcc 开关finit-local-vars,补丁在这里https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00615.html

我希望这最终会合并到 gcc 主分支并被广泛采用。从字面上看,我见过的每个代码风格指南都要求 C/C++ 编码人员= 0在定义变量的任何地方进行显式零赋值。这是容易出错且毫无意义的猴子工作。

于 2019-03-23T23:57:15.157 回答