我目前正在制作一个旧的内存安全项目。
在这个项目中,我有一个2D数组,其中填充了指向我自己的类Block
实例的指针。
这样声明:
Block* gemGrid[xMax][yMax];
然后像这样填充:
for(int i = 0; i<8; i++)
{
for(int j = 0; j<8; j++)
{
//do stuff here
gemGrid[i][j] = new Block(i,j, gridOffset);
}
}
这很好用。
我有了创建unique_ptr<Block>
的2D阵列而不是Block*
的想法。
我决定这样声明:
unique_ptr<Block> gemGrid[xMax][yMax];
并像这样填充:
for(int i = 0; i<8; i++)
{
for(int j = 0; j<8; j++)
{
gemGrid[i][j].reset( new Block(i,j, gridOffset));
}
}
然而,当我尝试这样做时,编译器决定完全忽略第二个for循环("j"递增的部分),只创建一个一维数组。
这让我想问,C++
在2D阵列中与unique_ptrs
有问题吗?我应该只使用指向Block
s的指针的2D数组,并使用一个unique_ptr
来确保这个数组在超出范围时被杀死吗?
C++对unique_ptr
的二维数组没有任何异议。
你提供的两个替代方案对我来说似乎不是真正的替代方案。如果你有一个unique_ptr
到Block*
的二维数组,并且你使用new
分配Block
的xMax * yMax
实例,并将指向它们的指针存储在数组中,那么谁或什么将释放Block
的这些实例?unique_ptr
当然不是。因此,"我应该这么做吗"的答案几乎肯定是"不",因为你会有内存泄漏。
分配Block
实例的二维布局的最"明显"的方法是定义Block
的二维数组(使用内置数组或std::array
(如果可用))。如果你能识别出任何不适合你的东西,那么有人可以为你的旧代码提出一种替代方法,以避免内存泄漏。
[回应上面的评论]完成Block gemGrid[xMax][yMax];
后,如果需要的话,可以获得一个指向Block对象的指针,如下所示:&gemGrid[i][j]
。需要一个指针与内存分配完全无关。指针是new
允许您访问其分配的对象的方法,但无论如何分配,您都可以将指针指向对象。