C++, объект, созданный в куче против локального - при возврате указателя

Это дополнительный вопрос из Safe в C#, а не в C++, простой возврат указателя / ссылки,

Это:

person* NewPerson(void)
{
  person p;
  /* ... */
  return &p; //return pointer to person.
}

такой же как?

person* NewPerson(void)
{
  person* pp = new person;

  return pp; //return pointer to person.
}

Я знаю, что первая - плохая идея, потому что это будет дикий указатель. Во втором случае, будет ли объект безопасным в куче - и, как в C#, выйдет из области видимости, когда на него уйдет последняя ссылка?

5 ответов

Решение

Это безопасно, объект будет еще жив после возвращения.

Но не ждите, что объект будет автоматически очищен для вас в C++. Стандарт C++ не имеет сборки мусора. Вам нужно будет delete сам объект, или используйте некоторую форму умного указателя.

Да, второй случай безопасен.

Но звонящему нужно будет delete возвращенный указатель. Вы можете изменить это, чтобы использовать boost::shared_ptr и он будет уничтожен, когда он больше не используется:

boost::shared_ptr<person> NewPerson()
{
    boost::shared_ptr<person> pp = boost::make_shared<person>();

    return pp;
}

Если C++11, то вы можете использовать std::shared_ptr или же std::unique_ptr,

person* NewPerson(void)
{
  person* pp = new person;

  return pp; //return pointer to person.
}

Я знаю, что первая - плохая идея, потому что это будет дикий указатель. Во втором случае, будет ли объект безопасным в куче - и, как в C#, выйдет из области видимости, когда на него уйдет последняя ссылка?

Правильно для первого: он будет возвращать указатель на данные в стеке этой функции, которые будут исправлены и изменены после завершения функции.

Во втором случае: объект создается в куче, которая отделена от стека выполнения. Когда функция завершается, объект в куче безопасен и остается тем же. Однако C++ автоматически не выполняет сборку мусора, поэтому, если вы потеряете все ссылки на объект кучи, это приведет к утечке памяти - пространство объекта не будет восстановлено до завершения программы.

Как вы говорите, первый случай плох, так как указатель не будет действительным. Что касается второго случая, память в C++ не управляется, вы должны очистить после себя. C++ не отслеживает ссылки на нормальный указатель, вот что std::shared_ptr для.

Последнее безопасно. Тем не менее, C++ (обычно) не обеспечивает сборку мусора, и поэтому вам необходимо организовать явное delete возвращенного объекта.

Другие вопросы по тегам