【发布时间】:2018-05-16 02:20:19
【问题描述】:
作为我目前正在参加的课程的一部分,我们正在使用 C 语言使用自行开发的低级库,现在我们正在完成我们的最终项目,即游戏。
在某一点上,拥有一个包含有关当前游戏状态的一些重要信息的结构(作为一种对象)似乎是相关的,即指向玩家“对象”的指针(不能真正调用我们正在使用实际对象的模拟对象,可以吗?)。
它会是这样的:
typedef struct {
//Holds relevant information about game current state
state_st currstate;
//Buffer of events to process ('array of events')
//Needs to be pointers because of deallocating memory
event_st ** event_buffer;
//Indicates the size of the event buffer array above
unsigned int n_events_to_process;
//... Other members ...
//Pointer to a player (Pointer to allow allocation and deallocation)
Player * player;
//Flag that indicates if a player has been created
bool player_created;
} Game_Info;
问题如下:
如果我们要坚持本课程大部分内容中使用的设计理念,我们将使用Game_Info * create_game_info() 和destroy_game_info(Game_Info * gi_ptr) 等函数“抽象”这些“对象”,作为这些“对象”的构造函数和析构函数。对象”(另外,“成员函数”类似于update_game_state(Game_Info * gi_ptr),通过将通常隐含的this 作为第一个参数传递来表现得像C++)。
因此,作为检测 Game_Info“实例”中的玩家对象是否已被删除的一种方式,我将玩家指针与 NULL 进行比较,因为在所有“析构函数”中,在释放内存后,我设置了传递指向 NULL 的指针,表明对象已成功释放。
这显然会导致一个问题(我一开始没有检测到,因此当我仍然掌握正在发生的事情时修复它的 player_created bool 标志)这是因为指针是通过副本传递的,而不是通过引用,在调用“对象”“析构函数”后它没有设置为 NULL,因此将其与 NULL 进行比较并不是了解指针是否被释放的可靠方法。
那么,我写这篇文章是为了征求意见,说明解决这个问题的最佳方法是什么:
- 指示“对象”是否为“实例化”的标志 - 在比较中使用标志而不是
ptr == NULL来断言“对象”是否为“实例化” - 我目前正在使用的解决方案 - 将指针传递给指针(使用
&player而不是仅player调用函数)- 将启用设置为NULL - 在调用“析构函数”之后,将指针设置为上一级“级别”的 NULL
- 任何其他解决方案,因为我在 C 方面不是很有经验,并且可能忽略了解决此问题的更简单方法。
感谢您的阅读以及您可能提供的任何建议!
【问题讨论】:
-
“不能真正调用我们使用实际对象的模拟对象,对吗?” - C 标准可以,所以我不明白为什么你可以' t.
-
检查指针是否为 NULL 是执行此操作的正确方法,一旦您确保在“解构器”中释放内存,这将起作用。不要找到解决实际释放内存的方法。这样做当然会奏效,但是您会在此过程中造成内存泄漏,并且养成造成内存泄漏的习惯是不行的。
-
不必对“对象”、“实例”等感到害羞。如果您正在使用面向对象的方法进行编程,那么这就是 OOP,即使您使用的语言没有明确的支持为它。
-
重新阅读后,我还看到“将指针传递给指针(使用 &player 而不是仅播放器调用函数) - 将启用设置为 NULL”,我希望您的意思是释放该内存.. 不仅仅是将值设置为“NULL”。
-
@CoreyLakey 问题是我实际上是在释放内存,并执行类似
free(player_ptr); player_ptr = NULL;的操作但是,player_ptr 从未设置为 NULL,因为因为指针作为函数参数传递,所以它是通过副本传递,因此不可能更改指针本身的值,从而对函数的“外部范围”产生影响。这就是我所引用的问题,因为在某处调用播放器析构函数后,我不能简单地执行 if(p_ptr != NULL) 来知道它当前是否已分配:/