首页 > 解决方案 > Clang++ 无法检测到未初始化成员变量的使用

问题描述

使用带有编译器标志的 clang++ 版本 11 和 C++ 17,-Wall如果在初始化之前使用变量,clang 通常会报错。但是,它不会检测到以下情况:

struct Bar
{
  bool b1;
};

class Foo {
public:
  Foo()
    : b2(Bar{b2}.b1) // We are using b2 here before it is initialized, but clang doesn't complain
  { }

  bool b2;
};

这是我可以创建的最简单的示例。它似乎只在使用对象(Bar)的成员变量(b1)初始化构造函数(在本例中为 b2)中的成员变量时发生。有谁知道为什么 clang 无法在这里检测到问题?

我承认这是一个人为的例子,但它实际上给我带来了一个问题,我想理解它。

标签: c++c++17clang++

解决方案


在一般情况下,无法在初始化之前检测您是否使用了成员变量。对一般程序这样做违反了赖斯定理。

编译器不要尝试。

相反,他们有一些简单而廉价的启发式方法来捕捉常见情况。

不能依赖编译器来检测使用未初始化变量的每种情况。

在这种特殊情况下,您b2在初始化之前传递给另一个类,但仅使用它来初始化临时变量。然后用于初始化最初初始化的变量。

如果这是你最简单的情况,clang 做得很好。当您将变量用作其自己的初始化语句的一部分时,编译器往往会更糟。

这是一个更简单的情况:

class Foo {
public:
  Foo()
    : b2((bool const&)b2) // We are using b2 here before it is initialized, but clang doesn't complain
  { }

  bool b2;
};

另一个案例:

struct Bob {
    bool b;
    operator bool() const{ return b; }
};

class Foo {
public:
  Foo()
    : b2(Bob{b2}) // We are using b2 here before it is initialized, but clang doesn't complain
  { }

  bool b2;
};

其他

Bob bob = {Bob{bob.b}.b};

我可以继续。

Clang并不声称可以检测所有未初始化的变量使用。因此,它未能检测到一个不是“错误”。相反,让他们检测另一个未初始化的案例是一项新功能。


推荐阅读