简体   繁体   English

C++ 结构指针崩溃,在没有 {} 的情况下初始化

[英]C++ struct of pointers crash, when initialized without {}

While refactoring a C-style struct to C++, I am facing a crash when creating a new object of the struct without {}.在将 C 样式结构重构为 C++ 时,我在创建没有 {} 的结构的新 object 时遇到崩溃。

I have illustrated the problem with the following code snippet.我已经用下面的代码片段说明了这个问题。

struct A {
    A() = default;
    int* a1;
    int* a2;
};

int main()
{
    A a{};
    std::cout << a.a1 << std::endl; //print 0000000000000000(nullptr)

    A b;
    std::cout << b.a1 << std::endl; //crash (0xcccccccccccccccc)
}

Why a.a1 is initialized to nullptr while b.a1 is not nullptr?为什么 a.a1 被初始化为 nullptr 而 b.a1 不是 nullptr?

What is different between the two constructed objects?两个构造对象之间有什么不同?

I know a solution could be:我知道解决方案可能是:

struct A {
    A() = default;
    int* a1 = nullptr;
    int* a2 = nullptr;
};

Thanks,谢谢,

If you use {} , everything in the class isvalue-initialized .如果您使用{} ,则 class 中的所有内容都是value-initialized So, pointers become null-pointer, integers become 0, booleans become false, etc. If you don't, then the fields are default initialized with indeterminate values.因此,指针变为空指针,整数变为 0,布尔值变为 false,等等。如果不这样做,则这些字段默认使用不确定的值初始化 Using these values in any way causes undefined behavior.以任何方式使用这些值都会导致未定义的行为。


If you want everything to be deterministically initialized regardless, here is one way to do that:如果您希望无论如何都确定性地初始化所有内容,这是一种方法:

struct A {
    int* a1 = nullptr;
    int* a2 = nullptr;
};

Here, anything you don't initialize explicitly is initialized for you.在这里,您未显式初始化的任何内容都会为您初始化。 But the class is no longer trivially-constructible .但是 class 不再是微不足道的构造

Read more about initialization in cppreference .cppreference中阅读有关初始化的更多信息。

Why a.a1 is initialized to nullptr为什么 a.a1 被初始化为 nullptr

Because you value initialised a .因为您重视初始化a Empty braces are syntax for value initialisation.空括号是值初始化的语法。

while b.a1 is not nullptr?而 b.a1 不是 nullptr?

Because you default initialised b .因为您默认初始化b Lack of any initialiser is syntax for default initialisation.缺少任何初始化程序是默认初始化的语法。

What is different between the two constructed objects?两个构造对象之间有什么不同?

One is value initialised and the other is default initialised.一个是值初始化,另一个是默认初始化。

I am facing a crash我正面临崩溃

The class is trivial(ly default constructible) . class 很简单(默认可构造) When a trivial class is default initialised, its members are default initialised as well.当一个普通的 class 被默认初始化时,它的成员也被默认初始化。 A default initialised fundamental object such as a pointer has an indeterminate value.默认初始化的基本 object(例如指针)具有不确定的值。 Such value is also commonly called "uninitialised".这样的值通常也称为“未初始化”。

Reading an indeterminate value results in undefined behaviour (there are rare exceptions which do not apply to this example).读取不确定的值会导致未定义的行为(有少数例外情况不适用于此示例)。 Crash is a possible outcome of undefined behaviour.崩溃是未定义行为的可能结果。

A decent compiler will warn you about the bug with a message such as this if you ask to be warned about bugs:如果您要求收到有关错误的警告,一个体面的编译器会警告您有关错误的消息,例如:

warning: 'b.A::a1' is used uninitialized in this function [-Wuninitialized]

Conclusions: Do not read uninitialised objects.结论:不要读取未初始化的对象。 Always initialise or at least assign all objects before first read.始终在第一次读取之前初始化或至少分配所有对象。 Use compiler warnings.使用编译器警告。 Do not ignore compiler warnings.不要忽略编译器警告。 Avoid undefined behaviour.避免未定义的行为。

It is known as uniform initialization it will initialize all the class variables with default values它被称为统一初始化,它将使用默认值初始化所有 class 变量

    A a{};

You created the object here but you have to manually initialize all the class variables您在这里创建了 object 但您必须手动初始化所有 class 变量

A b

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

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