Man*_*mar 3 c++ constructor initialization compiler-warnings c++11
#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;
}
Run Code Online (Sandbox Code Playgroud)
如果我们编译并运行上面的代码,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
Run Code Online (Sandbox Code Playgroud)
对于上述程序,编译器会发出有关变量内部函数的未初始化使用的警告.但是,当函数尝试使用类型对象的变量时,编译器不会发出警告.abar()foo()xoastruct a
我知道这个c++11 universal initialization特性,如果我们定义struct a如下,那么内置int类型的默认构造函数将被默认的构造函数调用struct a.
struct a {
int x{};
}
Run Code Online (Sandbox Code Playgroud)
我想知道,type traits/static_assert在上述情况下,有新功能可以实现这样的警告信息吗?
这样的事情在C#这样的语言中是可能的,因为一切都是从公共类派生的,因此默认构造函数会关注这一点.Bjarne Stroustrup在他的" C++编程语言 "中提到了这个问题,因为这种并发症的原因是为了提高罕见危急情况下的性能.
struct Buf {
int count;
char buf[16?1024];
};
Run Code Online (Sandbox Code Playgroud)
Buf在将其用作输入操作的目标之前,我们可以使用a 作为局部变量而不初始化它.但我认为如果我们能够实现某种机制来处理这个问题,那么在很多情况下它会很棒.这非常有用,因为未初始化的变量使用会导致非确定性错误的主要来源.
这只能在非常简单的情况下实际工作,如此处所示.在其他情况下,编译器甚至无法在使用前判断成员变量是否已初始化.例如:
// 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;
}
Run Code Online (Sandbox Code Playgroud)
由于init_a()未在与转换单元相同的转换单元中定义test(),因此编译器无法知道在到达语句x时是否分配了成员return.
所以,这样的警告只能在编译器能够证明该成员可能不被初始化的情况下被触发,并有很多情况下,编译器不能告诉我们,将无法产生警告.因此,有这样的警告只能捕获非常简单的情况,并且用处非常有限.