在具有多个返回点的功能中清理的正确方法
Proper Way to Cleanup in a Function with Multiple Return Points
我有一个递归搜索算法,我想在每次通话后清理指针。但是,我在很多位置返回,在每个人面前放置delete
或free
似乎很草率。
有更好的方法吗?我是否在函数返回时将它们全部释放,这意味着我应该在堆栈上分配它们,而不是在堆上分配?
请注意,这是一个并行的搜索(未在代码中显示(,但是呼叫者将永远不会在孩子之前返回。这是否还有其他用于使用堆栈的陷阱?
示例代码(不必担心此处的算法(:
//create a new struct state (using new), initialize and return (C style)
new_state()
free_list(state* node)//free a list
double minimax(state* node, state* bestState) {
if (base_case) {
return;
}
state* gb = new_state(); //single node
state* children = new_state(); //head of list
generate_children(children); //fill list
state* current = children; //traverse node
//recurse on child
double result = -minimax(current, gb);
if (case1) {
free(gb);
free_list(children);
return;
}
if (case2) {
//do stuff
}
while(current != NULL){
result = -minimax(current, gb);
if (case1) {
free(gb);
free_list(children);
return;
}
if (case2) {
//do stuff
}
current = current->next;
}
free(gb);
gb = NULL;
//More stuff (with children but not gb)
free_list(children);
return;
}
这是raii的一小部分:
首先,我们有一个struct
,它只是存储您的物品。
struct FreeAll
{
state* gb;
state* children;
FreeAll(state* g, state* c) : gb(g), children(c) {}
~FreeAll() { free(gb); free(children); }
};
请注意,在破坏时,free()
在这两个项目上都被调用。如何使用它?
double minimax(state* node, state* bestState)
{
if (base_case) {
return;
}
state* gb = new_state(); //single node
state* children = new_state(); //head of list
// Initialize our small RAII object with the above
// pointers
FreeAll fa(gb, children);
generate_children(children); //fill list
state* current = children; //traverse node
//recurse on child
double result = -minimax(current, gb);
if (case1) {
return;
}
if (case2) {
//do stuff
}
while(current != NULL){
result = -minimax(current, gb);
if (case1) {
return;
}
if (case2) {
//do stuff
}
current = current->next;
}
//More stuff (with children but not gb
return;
}
本地变量fa
是FreeAll
类型。当此局部范围范围内时,称为fa
的破坏者,它在struct
中存储的两个指针上都称为free
。还要注意,在返回点上缺少任何代码以释放内存。这将由fa
完成范围时完成。
请注意,这是一个简单的例子,没有像其他方法一样具有复杂性,但是它为您提供了RAII范式的基本要素。
但是,我在许多地方返回,在每个人之前放置一个或免费的删除似乎是草率的。
是的。
有更好的方法吗?
是。明智的指针是更好的方法。但是,如果您不想放弃自己正在做的事情,并在继续之前学习如何使用智能指针(可能是第一次很难(继续阅读。
我是否在函数返回时释放它们,这意味着我应该在堆栈上分配它们,而不是在堆上分配?
是的,您可以做到。它的性能也更好。但是,如果您打算分配大量内存,它将无效。
请注意,这是一个并行的搜索(未在代码中显示(,但是呼叫者将永远不会在孩子之前返回。这是否还有其他用于使用堆栈的陷阱?
陷阱是相同的。使用并行代码,您必须小心。
有很多方法可以避免此问题。已经提到了智能指针和堆栈分配。
另一种方法就是只有一个出口。这有时会变得笨拙,因为例如,这意味着您必须在循环中设置一个标志,然后才能突破它,以知道它是成功终止还是由于错误。
另一种方法是在函数A中分配指针,调用函数B进行实际工作(将其传递给分配的指针(,然后一旦函数B返回函数A,释放了指针。
<</p>scopeguard为您完成工作。
https://en.wikibooks.org/wiki/more_c++; idioms/scope_guard
void your_function()
{
Scope_guard const final_action = []{
free(gb);
free_list(children);};
// your code here
};
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何使用 C/C++ 和 system() 系统调用以外的其他方法在 Linux 中获取文件功能?
- C++中SFINAE的功能方法
- 如何定义和设置指向模板类方法的功能指针
- 将C 方法作为功能指针传递
- 寻找一种加速功能的方法
- 单位测试私人方法通过使其自由功能
- 如何通过功能指针调用派生方法
- 在具有多个返回点的功能中清理的正确方法
- C 模板功能是否有任何方法可以采用n个参数
- 是否有一种方法可以避免在RVALUE和LVALUE参考中创建功能时避免重复的代码
- 从功能指针调用方法
- 早期回报构成功能的最简短方法
- 实现交换/复制功能:有没有更好的方法
- 正确的方法将功能限制为特定数据类型
- 测试模拟功能的最佳方法
- C 获得超载成员功能指针的通用方法
- 有什么方法可以将此功能分开并插入空间
- C 中重复的构造函数和方法功能
- c++的static_cast和虚方法功能