Должны ли мы удалить указатель, который не является новым / malloc нами? - PullRequest
6 голосов
/ 03 ноября 2010
class ClassA
{
public:
    ClassA(ClassB *p) b(p){}
    ~ClassA(){delete b;}
    ClassB *b;
};

Это хороший дизайн?

Ответы [ 7 ]

9 голосов
/ 03 ноября 2010

Ответ зависит .Вы должны уточнить, кто отвечает за время жизни объекта.

Также ClassA не имеет определенного пользователем конструктора копирования и оператора присваивания, что может привести к неопределенному поведению.Например:

ClassA object1( new ClassB() ); //object1 takes ownership of the object
ClassA object2( object1 ); //object2 takes ownership of the same object
// now first object2 is destroyed and deletes the object
// then object1 is destroyed and double-delete happens

, поэтому ваш пример, вероятно, не очень хороший.

2 голосов
/ 03 ноября 2010

Вы имеете в виду:

class ClassA  { 
  ClassB *b;  
public: 
  ClassA(ClassB * p) {b = p;} 
  ~ClassA() {delete b;}  
};

Это не хороший дизайн. Тот, кто создает, должен быть тем, кто удаляет.

1 голос
/ 03 ноября 2010

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

В то же время, я бы не сказал, что передача владения объектами - это, безусловно, плохой дизайн, если это очевидно для пользователей ClassA в документации. Я сталкивался с подобной ситуацией, когда писал функции, которые берут указатель на объект и копируют его для собственного использования. Там, где это необходимо, я стараюсь комментировать эти функции с помощью «семантики копирования параметров» или чего-то такого, что говорит вызывающей стороне: «Вы можете делать с этим объектом то, что хотите, после того как я вернусь ... У меня есть собственная копия».

Если вы используете необработанные указатели, я считаю важным заключить такие контракты для вызывающих абонентов.

1 голос
/ 03 ноября 2010

В этом нет ничего плохого - технически вы передали право собственности на ClassB вместо экземпляра ClassA при создании (т. Е. Экземпляр ClassB существует до того, как потребуется ClassA, но как только ClassA создан, он становится владельцем Класс B).

Является ли это хорошим дизайном или нет, зависит от контекста, в котором он применяется. Например, имеет ли смысл, что ClassA становится владельцем ClassB? Если вы используете умный указатель вместо «старого» указателя?

1 голос
/ 03 ноября 2010

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

0 голосов
/ 03 ноября 2010

В общем, это плохая идея.Довольно часто вы просто не знаете, как был создан объект ClassB.Это может быть указатель на элемент массива, созданный с помощью оператора new [], или он может быть передан вам из отдельной библиотеки DLL, которая использует специальный распределитель памяти.В этих случаях использование оператора delete для удаления этого указателя будет серьезной ошибкой.

0 голосов
/ 03 ноября 2010

Обычно, нет, это запутанный / противоречивый дизайн (обычно вы хотите, чтобы соответствующие new и delete происходили на одном уровне). Однако есть некоторые исключения; например, интеллектуальные указатели снабжаются необработанным указателем, а затем становятся владельцем объекта, поэтому они отвечают за вызов delete, когда он больше не нужен.

...