C++堆分配和内存重用

Æle*_*lex 3 c++ memory-management heap-memory

我有这个小片段:

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;
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
Run Code Online (Sandbox Code Playgroud)

如果这看起来很简单,我很抱歉,这是我一段时间以来一直想知道的事情.什么是正确的,删除​​内存然后重新分配,或者我可以立即重新分配?

编辑:

会更好吗?

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;
}
Run Code Online (Sandbox Code Playgroud)

此函数的调用者需要一个已添加到状态的新操作,因此必须在此处进行删除.

pax*_*blo 7

您在该代码中可能存在内存泄漏,因为每次循环都会创建一个操作,但如果无法添加,则不会释放它.更好的方法是将动作创建移到循环之外,例如:

Action *newAction (Agent& a, ACTION_MODE& m) {
    Action *new_action = new Action(a,m);
    while (!state->addAction(new_action))
        ;
    return new_action;
}
Run Code Online (Sandbox Code Playgroud)

这比连续删除和重新创建操作更有效,应优先使用.

我还修复了返回类型,以便编译器不会抱怨,如果你永远无法添加动作,你应该引入某种失败策略.

就像是:

Action *newAction (Agent& a, ACTION_MODE& m) {
    // Try to make action, return null if no go.

    Action *new_action = new Action(a,m);
    if (new_action == 0)
        return 0;

    // Try a limited number of times to add action to state.

    int limit = 10;
    while (!state->addAction(new_action)) {
        if (--limit == 0)
            break;
        // Optional sleep if desired.
    }

    // If that didn't work, delete action and return null.

    if (limit == 0) {
        delete new_action;
        return 0;
    }

    // Otherwise the action was added, return it.

    return new_action;
}
Run Code Online (Sandbox Code Playgroud)