动态数组内存分配如何工作

How does dynamic array memory allocation work?

本文关键字:工作 何工作 数组 内存 分配 动态      更新时间:2023-10-16

编辑:由于我发布了一个没有源代码的 TArray 的不当问题,我将其替换为 std::vector。

我在主函数中定义了一个动态数组

std::vector<sSymbols> arrSymbols; 

我还有一个函数,可以将新元素添加到数组中;

functionOne(std::vector<TSymbols>& arrSymbolsRef)
{
    sSymbols symbolOne;
    //some symbol struct filling
    arrSymbolsRef.push_back(symbolOne);
    for (int i = 0; i < arrSymbolsRef.size(); i++) 
       printf("arrSymbolsRef[%d] ptr is %d", i, &arrSymbolsRef[i]);
}

更新结果:在循环中运行此函数将给出以下结果:

arrSymbolsRef[0] ptr is -1242393600
arrSymbolsRef[0] ptr is -1257218304
arrSymbolsRef[1] ptr is -1257218244
New iteration
arrSymbolsRef[0] ptr is -1451463936
arrSymbolsRef[1] ptr is -1451463876
arrSymbolsRef[2] ptr is -1451463816
New iteration
arrSymbolsRef[0] ptr is -1450359040
arrSymbolsRef[1] ptr is -1450358980
arrSymbolsRef[2] ptr is -1450358920
arrSymbolsRef[3] ptr is -1450358860
New iteration
arrSymbolsRef[0] ptr is -1243432448
arrSymbolsRef[1] ptr is -1243432388
arrSymbolsRef[2] ptr is -1243432328
arrSymbolsRef[3] ptr is -1243432268
arrSymbolsRef[4] ptr is -1243432208
New iteration
arrSymbolsRef[0] ptr is -1243432448
arrSymbolsRef[1] ptr is -1243432388
arrSymbolsRef[2] ptr is -1243432328
arrSymbolsRef[3] ptr is -1243432268
arrSymbolsRef[4] ptr is -1243432208
arrSymbolsRef[5] ptr is -1243432148
New iteration
arrSymbolsRef[0] ptr is -1550211968
arrSymbolsRef[1] ptr is -1550211908
arrSymbolsRef[2] ptr is -1550211848
arrSymbolsRef[3] ptr is -1550211788
arrSymbolsRef[4] ptr is -1550211728
arrSymbolsRef[5] ptr is -1550211668
arrSymbolsRef[6] ptr is -1550211608

为什么在某些时候地址会发生变化?

我需要创建一个指向这些元素的指针数组,并在每次增加 arrSymbol 时添加新元素(指针)。

但是经过几次迭代后,数组中的指针指向了错误的数据。

就像我在问题的评论中所说的那样,你不能一直依赖类的存储都在同一个地方。当你向它添加元素时,它很可能必须增长 - 为此,它将分配一个新的、更大的块,并将所有当前数据复制到其中。

仅供记录,std::vector也没有提供这种行为。这个简单的程序:

int main()
{
    std::vector<int> a;
    for(int i = 0 ; i < 17 ; ++i) {
        a.push_back(i);
        std::cout << "Iteration " << i << " : "
                  << static_cast<void*>(&a[0]) << 'n';
    }
}

在我的系统上给出以下结果:

Iteration 1 : 0x1aa9050
Iteration 2 : 0x1aa8c20
Iteration 3 : 0x1aa8c20
Iteration 4 : 0x1aa9070
Iteration 5 : 0x1aa9070
Iteration 6 : 0x1aa9070
Iteration 7 : 0x1aa9070
Iteration 8 : 0x1aa90a0
Iteration 9 : 0x1aa90a0
Iteration 10 : 0x1aa90a0
Iteration 11 : 0x1aa90a0
Iteration 12 : 0x1aa90a0
Iteration 13 : 0x1aa90a0
Iteration 14 : 0x1aa90a0
Iteration 15 : 0x1aa90a0
Iteration 16 : 0x1aa90f0

如您所见,矢量存储的起始地址更改了几次。现在,由于std::vector保证其元素的连续存储,因此其所有元素的地址也会更改。

我认为没有任何可动态调整大小的容器可以保证其元素的常量地址,除非您预先声明了可以存储的最大元素数量。在这种情况下,它可以一次分配一个巨大的块,而不会再次重新分配。如果您需要此类行为,请考虑使用类似 std::array 的东西,或者围绕不允许修改其大小的std::vector创建一个包装器。