Предотвратить утечки памяти в шаблоне - PullRequest
1 голос
/ 07 февраля 2012

У меня есть шаблон

template <class T>
class A
{
  T* t_;
  A(){t_ = new T();}

  void SetItem(T& t)
  {
     t_ = t;
  }

};

В этом классе шаблонов есть 2 случая

1. A<T> a;
2. A<T*> b;

Если я призываю два раза SetItem, т.е.

a.SetItem(T());
a.SetItem(T());

память будет очищена правильно?

То же самое, если я призываю так:

b.SetItem(new T());
b.SetItem(new T());

Я знаю, что память не будет очищена.

Вопросы:

  1. Как сделать ограничение на шаблон, чтобы он занимал только T или T*?
  2. Если я использую шаблон A<T*>, как предотвратить утечки. Должен ли я изменить класс или позаботиться об этом снаружи?
  3. Есть ли способ заставить эту работу работать, когда я использую A<T> или A<T*>?

Я думаю, что использование интеллектуальных указателей или автоматических указателей является опцией. Но я точно не знаю.

Ответы [ 3 ]

4 голосов
/ 07 февраля 2012

Быстрый ответ заключается в том, что человек, использующий класс A, может очистить память, выделенную для кучи. Если вы используете std :: list и храните в нем указатели, то вы (не список) несете ответственность за вызов delete для них. Не пытайтесь заставить свой шаблонный контейнер обнаруживать указатели и удалять их.

Я бы вообразил, что если вы используете класс A с параметром шаблона указателя, то в какой-то момент вы вызовете delete при возврате из GetItem () (который, как я полагаю, класс предоставит).

(Кроме того, SetItem должен принимать const T &.)

0 голосов
/ 07 февраля 2012

A здесь бессмысленный класс.Решения для предотвращения утечки:

  • Используйте интеллектуальный указатель.Если ваш объект будет доступен для общего доступа, а вы не знаете времени жизни, вы можете использовать shared_ptr.Если это не так, и ваш класс A владеет объектом, используйте unique_ptr.

  • Не используйте указатель вообще, но используйте экземпляр T в вашем A. Это накладывает ограничения натип, который может содержать ваш класс A, но пользователи вашего класса могут сделать так, чтобы он содержал unique_ptr или shared_ptr, указав его как параметризованный тип.Например, вектор, который принимает объекты типа T, но пользователи могут заставить свои векторы принимать shared_ptr или unique_ptr.

  • Вы должны указать, если ваш класс становится владельцем, если пользователь передает указатель.Если так, то ваш класс действительно сам по себе умный указатель.

Какой из них использовать довольно сложно определить в вашем примере, поскольку у А нет цели в существующей форме.

0 голосов
/ 07 февраля 2012

Чтобы избежать утечек, у вас должен быть деструктор, который будет delete T, когда объект A разрушен.

Чтобы ваш шаблон мог использовать только указатели, вы должны использовать черты типа. Я не совсем знаком с ним, чтобы привести пример.

 template <class T>
    class A
    {
      T* t_;
     //Set t_ to nullptr, as you are able to pass new T() to SetItem
      A() : t_(nullptr) {}
      ~A() { delete t_; }  // When A is destroyed, t_ will be deleted.
      void SetItem(const T& t)
      {
         t_ = t;
      }

    };
...