C++ C++;类实例未初始化但没有编译错误,为什么

C++ C++;类实例未初始化但没有编译错误,为什么,c++,initialization,C++,Initialization,我的问题是关于以下代码: #include <stdio.h> #include <iostream> #include <string> using namespace std; class Blob { public: int age; void hello() { printf("hello\n"); } }; void test_case() { Blob a; //a.hello(); //(1)

我的问题是关于以下代码:

#include <stdio.h>
#include <iostream>
#include <string>

using namespace std;

class Blob {
public:
    int age;
    void hello() { printf("hello\n"); }
};

void test_case() {
    Blob a;
    //a.hello();         //(1)
    cout << a.age << endl;
}

int main() {
    test_case();
    return 0;
}
#包括
#包括
#包括
使用名称空间std;
类Blob{
公众:
智力年龄;
void hello(){printf(“hello\n”);}
};
无效测试用例(){
斑点a;
//a、 你好();/(1)

cout事实上,它与是否注释掉无关。
a.hello();
Blob
总是有a,否则
Blob a;
将无法编译

(强调矿山)

如果没有为类提供任何类型的用户声明构造函数 类型(结构、类或联合),编译器将始终声明 默认构造函数作为其类的内联公共成员

如果隐式声明的默认构造函数未定义为 删除,定义(即生成函数体并 如果使用odr,则由编译器编译),并且它与 具有空正文和空初始值设定项列表的用户定义构造函数


因此,
a.age
是一个不确定的值,任何对它的访问(比如
cout事实上它与是否注释无关
a.hello();
Blob
总是有一个,否则
Blob a;
将无法编译

(强调矿山)

如果没有为类提供任何类型的用户声明构造函数 类型(结构、类或联合),编译器将始终声明 默认构造函数作为其类的内联公共成员

如果隐式声明的默认构造函数未定义为 删除,定义(即生成函数体并 如果使用odr,则由编译器编译),并且它与 具有空正文和空初始值设定项列表的用户定义构造函数


因此,
a.age
是一个不确定的值,任何对它的访问(比如
cout这里有2个点)

第一个是未定义的行为问题。由于你没有初始化年龄,它包含一个不确定的值,如果你使用它,它会导致UB(更多细节见宋元耀的答案)。添加一条额外的指令不会改变这一点

接下来是编译器消息。编译器不需要发出任何针对UB的警告。如果只在一种情况下引发错误,则您的警告并不特别一致,但程序员应该永远不会编写UB。因此,您不能真正责怪编译器没有发出警告


TL/DR:不要指望C++编译器在编写错误代码时总是发出警告。没有警告是必要条件,但不是足够的。

这里有2点。

第一个是未定义的行为问题。由于你没有初始化年龄,它包含一个不确定的值,如果你使用它,它会导致UB(更多细节见宋元耀的答案)。添加一条额外的指令不会改变这一点

接下来是编译器消息。编译器不需要发出任何针对UB的警告。如果只在一种情况下引发错误,则您的警告并不特别一致,但程序员应该永远不会编写UB。因此,您不能真正责怪编译器没有发出警告


TL/DR:不要指望C++编译器在编写错误代码时总是发出警告。没有警告是必要条件,但不是足够的。

未初始化变量(包括对象成员变量)将具有不确定的值(它可以被看作是随机的或垃圾的)。。访问此不确定值会导致。未定义的行为是不好的,并且可以做任何事情,从看似正常工作到。
a.hello();
不应更改任何内容,变量仍处于未初始化状态。它只是因为某种原因而混淆了编译器。“编译器将自动帮助我定义默认构造函数的以下4种情况”AFAIK,默认构造函数总是生成的,除非您添加自定义构造函数。@某个程序员我只是好奇为什么在VS2017中,它抱怨我“未初始化值错误”,但在我调用
a.hello()之后
它不再抱怨了。你是对的,我不应该写任何UB。我在MacOS的g++下测试过,它不会抱怨没有初始化
a的值,不管我调用
a.hello()不。只觉得困惑和失去信心相信C++编译器。@ HyyBraskCyter是的,你是对的,因为我没有使用<代码> =删除< /C> >,C++编译器将为我粘贴的代码定义默认构造函数。未初始化的变量(包括对象成员变量)将有不确定的值。(它可能被视为随机或垃圾)。访问此不确定的值会导致。未定义的行为是不好的,并且可以做任何事情,从看似工作正常到。
a.hello();
不应更改任何内容,变量仍然未初始化。它只是因为某种原因而混淆了编译器。”以下4种情况下,编译器将自动帮助我定义默认构造函数“AFAIK,除非您添加自定义构造函数,否则始终会生成默认构造函数。@Someprogrammerdude我只是好奇为什么在VS2017中,它会抱怨我“未初始化值错误”,但在我调用
a.hello()之后
它不再抱怨了。你是对的,我不应该写任何UB。我在MacOS的g++下测试过,它不会抱怨没有初始化
a的值,不管我调用
a.hello()<代码> >或>不。只觉得困惑和失去信心C++ C++编译器。@ HyyBraskCyter是的,你是对的,因为我没有使用<代码> =删除< /C++ >,C++编译器将为我粘贴的代码定义默认构造函数。谢谢你指出C++编译器警告是不够的。谢谢你指出C++编译器Wurnin。G是不够的。谢谢你给出这么详细的答案。事实上,在开始的时候
class Blob {
public:
    int age;
    void hello() { printf("hello\n"); }
    Blob() : age(42) {}
};