Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Memory Golang append内存分配与STL push_back内存分配_Memory_Stl_Go - Fatal编程技术网

Memory Golang append内存分配与STL push_back内存分配

Memory Golang append内存分配与STL push_back内存分配,memory,stl,go,Memory,Stl,Go,我比较了Goappend函数和STL向量。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

我比较了Go
append
函数和STL
向量。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;
}

更新

有关Golang内存分配策略,请参阅注释


对于STL,策略取决于实现。有关更多信息,请参阅。

您得到的是指向切片标头的指针,而不是实际的备份数组。您可以将切片头视为类似于

type SliceHeader struct {
    len,cap int
    backingArray unsafe.Pointer
}
追加并重新分配备份数组时,指针
backingArray
可能会更改(不一定,但可能会更改)。但是,包含长度、上限和指向支持数组的指针的结构的位置没有改变——它仍然在声明它的堆栈上。尝试打印
&arr[0]
而不是
&arr
,您会看到更接近预期的行为


顺便说一句,这与std::vector的行为几乎相同。将一个切片比作一个神奇的动态数组,更接近于<>代码>向量>代码。

你的GO和C++代码片段是不等价的。在C++函数中,您正在打印向量中第一个元素的地址,而在GO示例中,您正在打印切片本身的地址。

就像C++ ++代码:STD::vector < /COD>,GO切片是一个小数据类型,它保存指向包含数据的基础数组的指针。该数据结构在整个函数中具有相同的地址。如果您想要切片中第一个元素的地址,可以使用与C++中相同的语法:

&arr[0]

,谢谢您的评论。顺便问一下,您能解释一下magic incremental allocation的区别吗?Go策略似乎是将备份数组大小增加一倍,最多1024个元素,然后以25%的增量增加。我不确定STL实现使用的是什么策略。
type SliceHeader struct {
    len,cap int
    backingArray unsafe.Pointer
}