简体   繁体   English

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

[英]C++ class instance not initialized but no compile error, why

My question is about the following code:我的问题是关于以下代码:

#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;
}

if I comment out (1), it compile success.如果我注释掉(1),它编译成功。 If uncomment out (1), compile error occur, eg in VS2017 it complains "using an unintialized local variable 'a'".如果取消注释 (1),则会发生编译错误,例如在 VS2017 中它会抱怨“使用未初始化的局部变量 'a'”。

I've searched in search engine for a while and now only know the following 4 cases that the compiler will automatically help me define the default constructor:我在搜索引擎搜索了一段时间,现在只知道编译器会自动帮我定义默认构造函数的以下4种情况:

  1. a class member is an instance of a class (say B), and class B have defined default constructor类成员是类的实例(比如 B),并且类 B 定义了默认构造函数

  2. a class is derived from another class (say B), and B has defined default constructor一个类派生自另一个类(比如 B),并且 B 定义了默认构造函数

  3. a class has virtual function一个类有虚函数

  4. any combination of the previous 3 cases.前 3 种情况的任意组合。

I'm curious that, if I comment out (1), will the compiler add a definition of constructor for the class Blob ?我很好奇,如果我注释掉 (1),编译器会为Blob类添加构造函数的定义吗?

In fact it has nothing to do with comment out or not a.hello();实际上它与注释掉与否无关a.hello(); , Blob always has a generated default constructor , otherwise Blob a; , Blob总是有一个 生成的默认构造函数,否则Blob a; won't compile.不会编译。

(emphasis mine) (强调我的)

If no user-declared constructors of any kind are provided for a class type (struct, class, or union), the compiler will always declare a default constructor as an inline public member of its class.如果没有为类类型(结构、类或联合)提供任何类型的用户声明的构造函数,编译器将始终将默认构造函数声明为其类的内联公共成员。

If the implicitly-declared default constructor is not defined as deleted, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used, and it has the same effect as a user-defined constructor with empty body and empty initializer list .如果隐式声明的默认构造函数没有定义为delete,则如果odr-used,则由编译器定义(即生成并编译一个函数体),与用户自定义构造函数的作用相同,为空主体和空的初始化列表

As the result, a.age is default-initialized to indeterminate value, any access to it (like cout << a.age; ) leads to UB.结果, a.age默认初始化为不确定值,任何对其的访问(如cout << a.age; )都会导致 UB。

3) when a base class or a non-static data member is not mentioned in a constructor initializer list and that constructor is called. 3) 当构造函数初始值设定项列表中未提及基类或非静态数据成员并且调用该构造函数时。

otherwise, nothing is done: the objects with automatic storage duration (and their subobjects) are initialized to indeterminate values .否则,什么都不做:具有自动存储持续时间的对象(及其子对象)被初始化为不确定值

It depends on your intent;这取决于你的意图; as the workaround you can add a user-defined default constructor.作为解决方法,您可以添加用户定义的默认构造函数。

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

There are 2 points here.这里有2点。

First is the Undefined Behaviour question.首先是未定义行为问题。 As you do not initialize age, it contains an indeterminate value which leads to UB if you use it (see songyuanyao's answers for more details on that).由于您没有初始化年龄,它包含一个不确定的值,如果您使用它会导致 UB(有关详细信息,请参阅 Songyuanyao 的答案)。 Adding an additional instruction does not change anything to that point.添加额外的指令不会改变任何东西。

Next is the compiler message.接下来是编译器消息。 Compilers are not required to issue any warning facing UB.编译器不需要针对 UB 发出任何警告。 Yours is not specially consistent if it raises the error in only one case, but the programmer is supposed to never write UB.如果它仅在一种情况下引发错误,则您的方法并不是特别一致,但是程序员应该永远不会编写 UB。 So you cannot really blame the compiler for not issuing the warning.所以你不能真的责怪编译器没有发出警告。

TL/DR: do not expect a C++ compiler to alway issue warning when you write incorrect code. TL/DR:不要期望 C++ 编译器在您编写不正确的代码时总是发出警告。 Having no warning is a necessary condition, but not a sufficient one.没有警告是必要条件,但不是充分条件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM