Kee*_*elx 0 c++ memory pointers memory-leaks allocation
好吧,所以我和其他人有些分歧,我希望有人比我们中的任何一个人都更了解c ++可以解决这个问题.假设我们在函数内部的某个代码块(对于tilemap引擎):
void loadTiles()
{
Tile* tile = new Tile();
Level->addTile(x, y, tile); //x and y are just arbitrary ints.
/* when addTile is called, it fills the values of the chunk of memory pointed to by tile to the predefined chunk of memory created in the Level object. */
//Then, to remove the dangling pointer safely,
tile = NULL;
} //Then the actual memory pointed to by tile is deallocated here.
Run Code Online (Sandbox Code Playgroud)
Level类有一个名为map [] []的2D Tile数组,它的addTile函数看起来完全像这样:
void Level::addTile(int x, int y, Tile *tile)
{
map[x][y] = tile;
}
Run Code Online (Sandbox Code Playgroud)
指向tile的内存被释放,指针不再指向不存在的对象,tile对象的值基本上被复制到Level对象的map [] []数组中.我是对的,还是我弄错了?另一个人争辩说这会导致内存泄漏.
让我们看看每段代码.
1)分配内存
Tile* tile = new Tile();
Run Code Online (Sandbox Code Playgroud)
这将在堆上创建一个新的Tile对象,并将内存地址存储在变量tile中.请记住,变量tile只是一个指针,而不是对象本身.
2)复制参考
void Level::addTile(int x, int y, Tile *tile) { map[x][y] = tile;}
Run Code Online (Sandbox Code Playgroud)
上述函数只需一个指针并将其保存到一个多维数组中以备将来使用.在列出的所有代码的上下文中,现在将有两个对象的引用...原始调用函数中的tile*和多维数组中的条目.再次,请记住这些是指针(只有4个字节,具体取决于您的系统架构).
3)将指针设置为NULL
tile = NULL;
Run Code Online (Sandbox Code Playgroud)
此代码的结果是指针变量tile将不再指向堆上创建的对象.但是,该对象仍然存在.此时,在所有代码的上下文中,由于map [] []数组,您仍然会有一个指向对象的指针.
实际上,您不需要这行代码.tile不是悬空指针,因为它指向一个有效对象(在将其设置为NULL之前).代码也不会破坏对象.由于tile是局部变量,因此当函数范围退出时它将被清除.只清理指针,而不是它指向的对象.在此方案中将其设置为NULL可实现除废物循环之外的极少数.
每个说法也不是内存泄漏.您仍然有一个指向map [] []数组中对象的有效指针,因此您始终可以使用该引用来清理内存.
4)你需要做什么
您需要在某处删除该对象.在C++中,这是delete关键字.
delete tile;
Run Code Online (Sandbox Code Playgroud)
要么
delete map[x][y];
Run Code Online (Sandbox Code Playgroud)
现在,请记住,一旦上面的代码运行,堆上的内存将被释放回操作系统,您的应用程序将无法再安全地访问内存.因此,对map [x] [y] - > {SomeMethod}的任何调用都将导致访问冲突异常.存储在map [x] [y]中的指针现在是一个悬空指针(它指向一个对该类型无效的内存地址).
如果您需要在销毁关卡之前从关卡地图中删除关卡,您可以执行以下操作:
void Level::deleteTile(int x, int y)
{
if (map[x][y] != NULL)
{
delete map[x][y];
map[x][y] = NULL;
}
}
Run Code Online (Sandbox Code Playgroud)
我还会将addTile方法更改为:
void Level::addTile(int x, int y, Tile *tile)
{
deleteTile(x, y);
map[x][y] = tile;
}
Run Code Online (Sandbox Code Playgroud)
最后,当你破坏Level对象时,你需要做这样的事情:
void ~Level()
{
for (int i; i<MaxX; i++)
{
for (int j; j<MaxY; j++)
{
delete map[i][j];
}
}
}
Run Code Online (Sandbox Code Playgroud)
在创建Level对象时,应该将map [] []数组清零,以便所有值也为NULL.由于map数组不是函数的本地数组,因此最好将其所有指针值设置为NULL,以便知道它何时包含有效指针以及何时不包含有效指针.
如果动态创建(使用new关键字)map [] []数组,则还需要使用delete关键字清理其内存.
希望这可以帮助.