C ++ освобождение памяти после возврата - PullRequest
2 голосов
/ 04 марта 2012

У меня есть этот вопрос относительно выделения памяти и освобождения в C ++.Вот ситуация: у меня есть метод foo, который выделяет память и затем возвращает этот объект:

Object foo () {
  Object *a = new Object();
  // Do something with this object...
  return *a;
}

и другой метод, который использует этот возвращаемый объект:

void bar () {
  Object a = foo();
  // Do something..
}

И мой вопросв какой момент я должен освободить память, которую я выделил?Когда я возвращаюсь из метода foo, панель методов получает копию этого объекта в своем стеке или получает доступ к этому объекту где-то в памяти?

Спасибо!Bart

Ответы [ 4 ]

5 голосов
/ 04 марта 2012

Вы не можете освободить этот объект.Это потеряно.Это утечка памяти.Вы никогда не должны (динамически) размещать его в первую очередь.Ваш код должен был выглядеть следующим образом:

Object foo () {
  Object a;
  // Do something with this object...
  return a;
}

Когда я возвращаюсь из метода foo, панель методов получает копию этого объекта в своем стеке или получает доступ к этомуобъект где-то в памяти?

Это копия все еще существующего недоступного объекта.

3 голосов
/ 04 марта 2012

Вы теряете память, потому что вы не возвращаете выделенный объект, а его копию. Самое простое решение - вообще не использовать новое

Object foo () {
  Object a;
  return a;
}

Если вам действительно нужен объект в куче, например если это полиморфный объект и вы возвращаете указатель на базовый класс, он будет выглядеть как

Base* foo () {
  Base *a = new Derived();
  return a;
}

Но этот код далек от хорошего. Это не исключение сохранения, которое также может привести к утечкам памяти. Поэтому вы почти всегда должны оборачивать новый с помощью умного указателя, такого как std :: unique_ptr (только c ++ 11), std :: auto_ptr или boost :: shared_ptr.

std::unique_ptr<Base> foo () {
  std::unique_ptr<Base> a(new Derived();
  return a;
}
1 голос
/ 04 марта 2012

Распределение памяти с помощью new говорит компилятору: «Не волнуйтесь, я знаю, что делаю: этот объект будет контролироваться мной». Это означает, что компилятор, действительно, не будет беспокоиться об этом, и вы будете ответственны за это. Лучшее решение: не делайте этого, если вы действительно не знаете, что делаете. Обратите внимание, что я почти уверен, что знаю, что делаю, и все же я обычно не использую new, потому что в этом нет необходимости!

В вашем примере вы хотите использовать

Object foo() {
    Object a;
    // do something
    return a;
}

Концептуально объект создается в стеке и копируется при его возврате. После завершения копирования локальный объект уничтожается. На практике это случается редко: поскольку локальный объект уничтожается сразу после копирования, компилятору предоставляется свобода делать то, что вы обычно хотите, а именно: объект a не копируется и не уничтожается, а фактически вернулся напрямую. Однако это должно привести к тому же результату (если это не так, ваш класс где-то сломан).

0 голосов
/ 04 марта 2012

В этом примере вы не можете.Поскольку вызывающая функция никогда не будет знать, где (или даже не знать), был ли создан динамический объект.Если бы вы использовали ссылки (или указатели), то вызывающие абоненты должны были бы освободить их, когда закончили использовать их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...