C++堆分配和内存重用
我有这个小片段:
Action* newAction(Agent& a, ACTION_MODE& m)
{
Action *new_action;
do
{
new_action = new Action(a,m);
}
while (!state->addAction(new_action));
return new_action;
}
state->addAction(Action *a);
如果添加了 *a 将返回 true,如果未添加 *a 将返回 false(检查 *a 是否已存在) )。
现在,我知道很多人认为 goto 是邪恶的,所以,在上面的代码片段中,在每个循环中重新分配 new_action ,而不删除它,这不是错误的吗?
下面的片段不是更“明智”吗?
retry :
Action *new_action = new Action(a,m);
if (state->addAction(new_action))
{
return new_action;
}
else
{
delete new_action;
goto retry;
}
如果这看起来很简单,我很抱歉,但这是我一段时间以来一直想知道的事情。什么是正确的,删除内存然后重新分配,或者我可以立即重新分配?
编辑:
这样会更好吗?
Action* newAction(Agent& a, ACTION_MODE& m)
{
// state will only allow an action to be added if it does not already exist
Action *new_action = new Action(a,m);
if (!new_action) return 0;
while (!state->addAction(new_action))
{
delete new_action;
new_action = new Action(a,m);
}
return new_action;
}
该函数的调用者期望一个已添加到状态的新操作,因此必须在此处进行删除。
I've got this small snippet:
Action* newAction(Agent& a, ACTION_MODE& m)
{
Action *new_action;
do
{
new_action = new Action(a,m);
}
while (!state->addAction(new_action));
return new_action;
}
state->addAction(Action *a);
will return true if *a was added, false if *a not added (checks to see if *a already exists).
Now, I know that goto's are considered evil from lots of people, so, In the above snippet, re-allocating new_action in every loop, without deleting it, isn't that wrong ?
Wouldn't the following snippet be more "sensible" ?
retry :
Action *new_action = new Action(a,m);
if (state->addAction(new_action))
{
return new_action;
}
else
{
delete new_action;
goto retry;
}
I'm sorry if this seems elementary but it is something I've wondered about for some time now. What is correct, to delete the memory and then re-allocate, or can I re-allocate instantly ?
EDIT:
Would that be better ?
Action* newAction(Agent& a, ACTION_MODE& m)
{
// state will only allow an action to be added if it does not already exist
Action *new_action = new Action(a,m);
if (!new_action) return 0;
while (!state->addAction(new_action))
{
delete new_action;
new_action = new Action(a,m);
}
return new_action;
}
The caller of this function expects a new action which has been already added to state, so therefore deletion must take place in here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
该代码中存在潜在的内存泄漏,因为每次循环都会创建一个新操作,但如果添加失败,则不会释放它。更好的方法是将操作创建移到循环之外,例如:
这比不断删除和重新创建操作更有效,并且应该优先使用。
我还修复了返回类型,以便编译器不会抱怨,如果您永远无法添加操作,您可能应该引入某种失败策略。
像这样的东西:
You have a potential memory leak in that code in that you are creating a new action every time through the loop but, if it fails to add, you don't free it. Better would be to move the action creation outside of the loop with something like:
This is more efficient than continuously deleting and re-creating the action and should be used in preference.
I've also fixed the return type so that the compiler won't complain, and you should probably introduce some sort of failure strategy if you are never able to add the action.
Something like:
不。这会更合理:
其中
addActionOrDelete
完全按照其说明进行操作。如果要将指针的所有权转移给另一个函数,那么该另一个函数必须对该指针的所有权负责。如果它无法添加它,那么它必须删除它。但说实话,我不明白为什么你要在循环中分配这些
Action
对象。state
的状态是否会发生变化,导致添加操作之前不起作用,但稍后可能会起作用?如果是这样,那么拥有一个state->addAction
会阻塞直到可以添加操作不是更有意义吗?为什么要进行分配?这看起来像 Java 或 C# 风格的代码。只需这样做:
这将创建临时
Action
对象。不需要堆分配。或者甚至更好:这些对象很难复制吗?
No. This would be far more reasonable:
Where
addActionOrDelete
does exactly what it says. If you are going to transfer ownership of a pointer to another function, then that other function must take responsibility for the ownership of that pointer. If it cannot add it, then it must delete it.But to be honest, I don't understand why you are allocating these
Action
objects in a loop anyway. Is the state ofstate
going to change, such that adding an action didn't work before, but it may work later? If so, wouldn't it make more sense to have astate->addAction
that will block until the action can be added?And why the allocation at all? This looks like Java or C#-style code. Just do this:
That will create temporary
Action
objects. No need for heap allocation. Or even better:Are these objects hard to copy?
如果您想保留当前的代码上下文,请进行 2 个小更改:
编辑:
我从 @paxdiablo 的回答中意识到,您实际上不需要继续分配和释放内存。只需按照他的建议执行此操作即可:
[注意:如果您要接受我的答案,请选择他的答案。]
If you want to retain your current code context then, do 2 small changes:
Edit:
I realized from @paxdiablo's answer that you actually don't need to keep allocating and deallocating the memory. Simply do this, as he suggested:
[Note: Choose his answer, if you are going to accept mine.]
使用
shared_ptr
或unique_ptr
会更明智。您不应该再在 C++ 中进行自己的内存分配。无论如何,我认为这不是使用 goto 的好地方。您正在实现循环,而这正是循环构造的用途。
以下是使用
unique_ptr
执行此操作的方法:Using a
shared_ptr
orunique_ptr
would be more sensible. You shouldn't be doing your own memory allocation in C++ anymore.In any case, I don't think that this is a good place to use a goto. You are implementing looping, and that's exactly what a loop construct is for.
Here's how to do it with
unique_ptr
:我会这样写:
如果您不喜欢从循环中间返回,请将其更改为break,但这意味着您还必须将new_action的声明移到循环之外。
我总是尝试将
new
和delete
配对。在这个函数中拥有一个,在它调用的函数中拥有一个,对我来说似乎是一种不好的做法。I would write it like this:
If you dislike returning from the middle of a loop, change it to break, but it means you have to move the declaration of
new_action
outside the loop as well.I always try to pair
new
anddelete
. Having one in this function, and one in the function it calls seems like a bad practice to me.