Golang 追加内存分配 VS. STL push_back 内存分配

我比较了 Goappend函数和 STL vector.push_back,发现不同的内存分配策略让我很困惑。代码如下:


// CPP STL code

void getAlloc() {

    vector<double> arr;

    int s = 9999999; 

    int precap = arr.capacity();

    for (int i=0; i<s; i++) {

        if (precap < i) {

            arr.push_back(rand() % 12580 * 1.0);

            precap = arr.capacity();

            printf("%d  %p\n", precap, &arr[0]);

        } else {

            arr.push_back(rand() % 12580 * 1.0);

        }

    }

    printf("\n");

    return;

}



// Golang code    

func getAlloc() {

    arr := []float64{}

    size := 9999999

    pre := cap(arr)

    for i:=0; i<size; i++ {

        if pre < i {

            arr = append(arr, rand.NormFloat64())

            pre = cap(arr)

            log.Printf("%d %p\n", pre, &arr)

        } else {

            arr = append(arr, rand.NormFloat64())

        }

    }

    return;

}

但是内存地址对于大小的增量是不变的,这让我很困惑。顺便说一句,这两种实现(STL VS. Go)的内存分配策略不同,我的意思是扩展大小。有什么优点或缺点吗?这是上面代码的简化输出[大小和第一个元素地址]:


Golang                            CPP STL

2 0xc0800386c0                    2  004B19C0

4 0xc0800386c0                    4  004AE9B8

8 0xc0800386c0                    6  004B29E0

16 0xc0800386c0                   9  004B2A18

32 0xc0800386c0                   13  004B2A68

64 0xc0800386c0                   19  004B2AD8

128 0xc0800386c0                  28  004B29E0

256 0xc0800386c0                  42  004B2AC8

512 0xc0800386c0                  63  004B2C20

1024 0xc0800386c0                 94  004B2E20

1280 0xc0800386c0                 141  004B3118

1600 0xc0800386c0                 211  004B29E0

2000 0xc0800386c0                 316  004B3080

2500 0xc0800386c0                 474  004B3A68

3125 0xc0800386c0                 711  004B5FD0

3906 0xc0800386c0                 1066  004B7610

大话西游666
浏览 253回答 2
2回答

达令说

你的 Go 和 C++ 代码片段不是等价的。在 C++ 函数中,您正在打印向量中第一个元素的地址,而在 Go 示例中,您正在打印切片本身的地址。与 C++ 一样std::vector,Go 切片是一种小型数据类型,它包含一个指向包含数据的底层数组的指针。该数据结构在整个函数中具有相同的地址。如果你想在片中的第一元素的地址,你可以使用相同的语法与C ++:&nbsp;&arr[0]。

慕哥9229398

您正在获取指向切片标头的指针,而不是实际的支持数组。您可以将切片标头视为一个结构,例如type SliceHeader struct {&nbsp; &nbsp; len,cap int&nbsp; &nbsp; backingArray unsafe.Pointer}当您追加并重新分配后备数组时,指针backingArray可能会更改(不一定,但可能)。但是,保存长度、上限和指向后备数组的指针的结构的位置不会改变——它仍然在你声明它的堆栈上。尝试打印&arr[0]而不是,&arr您应该会看到更接近您期望的行为。std::vector顺便说一下,这与 的行为几乎相同。将切片视为vector比魔术动态数组更接近 a 。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go