Освобождение unique_ptr перед возвратом из функции - PullRequest
1 голос
/ 29 декабря 2011

Я использую unique_ptr, чтобы передать const wchar_t указатель на функцию. Далее я хотел бы привести короткий пример:

bool MyClass::foo(unique_ptr<const wchar_t> display_name) {
  bool result = false;
  ....
  // Do something
  result = DoWork(display_name.get());
  ....
  // I have to call release to prevent getting an error
  display_name.release();
  return result;
}

До сих пор я думал, что мне не нужно вызывать release() метод unique_ptr перед тем, как покинуть область действия (возврат из функции), потому что содержимое unique_ptr будет автоматически удалено, если unique_ptr выходит за рамки. Но если не вызывать метод release(), я получаю следующую ошибку (VS 2010):

enter image description here

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

Ответы [ 2 ]

3 голосов
/ 29 декабря 2011

Основываясь на вашем описании и комментарии, я считаю, что это больше, что вы ищете:

bool MyClass::foo(const std::wstring& display_name)
{
  bool result = false;

  // Do something
  result = DoWork(display_name.c_str());

  return result;
}

Этот строковый объект является контейнером STL wchar_t, который имеет различные полезные методы.Одним из которых является c_str(), который возвращает const wchar_t* версию строкового содержимого в стиле c для обратной совместимости со старым кодом.Ваша функция DoWork может быть такой функцией, для которой требуется строка в стиле c, так что вышеприведенное будет работать для вас.


Теперь на умные указатели 101:

В C ++11 std::unique_ptr может использоваться для автоматического уничтожения объектов, размещенных в куче, освобождая от забот исключительного небезопасного кода и ручного управления памятью, что может привести к утечкам памяти и другим неприятным последствиям.Скажем, у вас был следующий код:

void LeakyFunction()
{
    double* ptr = new double;
}

Очевидно, что это утечка памяти, так как после окончания области действия LeakyFunction мы потеряли указатель на стек и больше не можем удалить то, на что он указывалкучаИтак, мы пишем это:

void LessLikelyLeakyFunction()
{
    double* ptr = new double;
    // do stuff
    delete ptr; // clean up heap
}

Это хорошо, но если вы не получили раннего возврата или не сгенерировали исключение во время выполнения части кода, которая возвращает вас к той же проблеме, что и раньше.Таким образом, люди начали писать собственные классы интеллектуальных указателей, которым принадлежало необработанное выделение памяти, выделяя при конструировании и освобождая при уничтожении.Эта концепция теперь стала стандартной через такие вещи, как std::unique_ptr, поэтому мы можем сделать следующее:

void SmartFunction()
{
    std::unique_ptr<double> ptr(new double);
    // do stuff
} // unique_ptr is smart and calls delete for you

Таким образом, независимо от того, когда закончится область действия функции, вам не нужно беспокоиться, что все будетубрано правильно. Короче говоря, если вы не используете new, вам не нужен умный указатель, а если вы его используете, то, вероятно, вам следует использовать умный указатель, чтобы сделать ваш код более надежным.

2 голосов
/ 29 декабря 2011

Через unique_ptr вы пытаетесь вызвать delete для указателя на строковую литеральную константу.

Вы должны разрешать вызов delete только для указателей, которые указывают на объекты, созданные с помощью new.

...