简体   繁体   English

结构中指针数组的初始化值

[英]Initialized values of array of pointers in a struct

Let's say I defined a struct that had an array of pointers to objects inside it, like so:假设我定义了一个结构,其中包含指向对象的指针数组,如下所示:

struct node {
    node *arr[10];
};

Then, I initialize an instance of the struct on the heap and check the contents of its array of pointers.然后,我在堆上初始化结构的一个实例并检查其指针数组的内容。

node *curr = new node;
for (int i = 0; i < 10; ++i) {
    if (curr->arr[i] == nullptr) std::cout << "null" << std::endl; 
} // this would print "null" 10 times in my tests in online IDEs and on QTCreator's C++ environment.

However, why do I see that each of the elements of the array is a nullptr?但是,为什么我看到数组的每个元素都是一个nullptr? Shouldn't it be a garbage value?它不应该是一个垃圾值吗? Is this default behavior for all structs with arrays of pointers?这是所有具有 arrays 指针的结构的默认行为吗?

I thought they should just be garbage pointers, not all nullptrs.我认为它们应该只是垃圾指针,而不是所有空指针。 Any tips on how to think about initialization of the node instance would be awesome!任何关于如何考虑node实例初始化的提示都会很棒! Thank you!谢谢!

It depends on the memory allocator's status, it's a black box for programmers.这取决于 memory 分配器的状态,它是程序员的黑匣子。 For your code snippet, we can check the corresponding assembly:对于您的代码片段,我们可以检查相应的程序集:

f():                                  # @f()
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     edi, 80
        call    operator new(unsigned long)
        mov     qword ptr [rbp - 8], rax
        mov     dword ptr [rbp - 12], 0

Only the operator new is called, since the struct is a plain old data type, we don't have a non-trivial constructor called here, the memory we allocated is untouched.只有操作符 new 被调用,因为结构是一个普通的旧数据类型,我们没有在这里调用一个非平凡的构造函数,我们分配的 memory 是不变的。

If we change the code slightly by inserting a memory allocation and deallocation with exactly same size with your struct:如果我们通过插入与结构完全相同大小的 memory 分配和释放来稍微更改代码:

#include <cstring>
#include <iostream>
#include <memory>
const size_t n = 10;
struct node {
  node *arr[n];
};

void f() {
  {
    std::unique_ptr<char[]> up(new char[sizeof(node)]);
    memset(up.get(), 0xff, sizeof(node));
  }

  node *curr = new node;
  for (int i = 0; i < n; ++i) {
    if (curr->arr[i] != nullptr) std::cout << "not null" << std::endl;
  }
}

int main(int argc, char *argv[]) {
  f();
  return 0;
}

We get garbage values now, this is because that we have allocated a memory block with the size sizeof(node) , and fill it with value then deallocate it immediately.我们现在得到垃圾值,这是因为我们分配了一个大小为sizeof(node)的 memory 块,并用值填充它,然后立即释放它。

For modern memory allocators, they tend to retain a memory pool for different size ranges to boost the performance by avoiding too frequent system call (You may reference the design for jemalloc , the one in libc is similar but much simpler).对于现代 memory 分配器,他们倾向于为不同的大小范围保留一个 memory 池,以通过避免过于频繁的系统调用来提高性能(您可以参考jemalloc的设计,libc 中的设计类似但更简单)。 In my code, we allocated a memory block with the size sizeof(node) and deallocate it, the memory will be held by the allocator.在我的代码中,我们分配了一个大小为sizeof(node)的 memory 块并释放它,memory 将由分配器持有。 Then we allocate a node with node *curr = new node;然后我们用node *curr = new node;分配一个节点, it's likely that we will get the same address returned by the previous allocation. ,我们很可能会得到与之前分配返回的地址相同的地址。 So we get the expected garbage value now, it will be a different case for complex programs with multiple threads, we will ignore the complex scenario here.所以我们现在得到了expected的垃圾值,对于具有多线程的复杂程序来说,情况会有所不同,我们将忽略这里的复杂场景。

To initialize variable in c++ is a good habit and can avoid many related bugs, I suggest always do it.在 c++ 中初始化变量是一个好习惯,可以避免许多相关的错误,我建议总是这样做。

Online demo .在线演示

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

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