Memory Golang append内存分配与STL push_back内存分配
我比较了GoMemory 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
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
}