如何获得/实施"未初始化使用警告"一个类的内置类型成员变量的消息?

时间:2014-10-19 05:15:19

标签: c++ c++11 constructor initialization compiler-warnings

#include<iostream>
struct a{   
   int x;
};

int foo() {
    a oa;
    return oa.x;
}

int bar() {
    int a;
    return a;
}

int main() {
    auto val = foo();
    std::cout<<val<<"\n";
    return 0;
}

如果我们编译并运行上面的sample.cpp,我们得到以下结果:

$g++ -Wall -std=c++11 sample.cpp -o sample
sample.cpp: In function ‘int bar()’:
sample.cpp:13:9: warning: ‘a’ is used uninitialized in this 
function [-Wuninitialized]
  return a;
         ^
$ ./sample 
-1643562384
$ ./sample 
991591024

对于上述程序,编译器会在a函数内发出有关未初始化用于变量bar()的警告。但是,当foo()函数尝试使用类型为x的对象oa的变量struct a时,编译器不会发出警告。

我知道c++11 universal initialization功能,如果我们定义struct a如下,那么int默认构造函数将调用内置struct a类型的默认构造函数

struct a {
   int x{};
}

我想知道像type traits/static_assert这样的新功能是否可以在上述情况下实施此类警告消息?

这些事情在 C#等语言中是可能的,因为一切都是从公共类派生的,因此默认构造函数会关注这一点。 Bjarne Stroustrup 在他的“ The C ++ Programming Language ”中提到过这个问题,因为这种并发症的原因是在罕见的关键情况下提高性能

struct Buf {
int count;
char buf[16∗1024];
};

在将Buf用作输入操作的目标之前,我们可以使用{{1}}作为局部变量而不进行初始化。但我认为如果我们能够实现某种机制来处理这个问题,那么在很多情况下它会很棒。这非常有用,因为未初始化的变量使用会导致非确定性错误的主要来源。

1 个答案:

答案 0 :(得分:5)

这只能在非常简单的情况下实际工作,如此处所示。在其他情况下,编译器甚至无法告诉成员变量是否在使用前初始化。例如:

// a.h

void init_a(a & an_a);

// a.cpp

#include "a.h"

void init_a(a & an_a) {
    an_a.x = 1;
}

// b.cpp

#include "a.h"

int test() {
    a oa;
    init_a(oa);
    return oa.x;
}

由于init_a()未在与test()相同的翻译单元中定义,因此编译器无法知道在到达x语句时是否分配了return成员

所以这样的警告只能在编译器能够证明该成员可能未被初始化的情况下触发,并且在许多情况下编译器无法告知并且无法产生警告。因此,有了这样的警告只能捕捉到非常简单的情况,并且用处非常有限。