Можно ли несколько раз удалить указатель с ++? - PullRequest
0 голосов
/ 23 августа 2011

Если у меня есть следующий пример:

test.h

class MyClass
{
public:
MyClass();
std::string name1;
std::string name2;
std::string type1;
std::string type2;

void method1(MyClass &obj1);
void method2(MyClass &obj2);
}

test.cpp

MyClass *mainObject = new MyClass();

MyClass::MyClass()
{
}
void MyClass::method1((MyClass &obj1)
{
//do stuff
mainObject=&obj1; //we populate some of the MyClass variables


}
void MyClass::method2((MyClass &obj2)
{
//do stuff
mainObject=&obj2; //we populate the rest of MyClass variables
}

Когда мне следует удалять mainObject внутри test.cpp? Должен ли я создать деструктор, чтобы клиент мог его удалить?

Ответы [ 7 ]

4 голосов
/ 23 августа 2011

Это хороший пример, который лучше всего решить, не думая об этом самостоятельно.

Используйте shared_ptr<MyClass> mainObject; (либо новую C ++ 11, либо версию Boost). Это сделает delete для вас.

Имейте в виду, method1() и method2() также должны принять аргумент shared_ptr. В настоящее время они делают очень плохую вещь: удаляют объект, который передается по ссылке.

2 голосов
/ 23 августа 2011

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

Ваш код написан неправильно.Вам следует delete mainObject;, как только вы попытаетесь назначить его с помощью &obj1 или &obj2.Но убедитесь, что вы делаете это только в первый раз.Не указывайте delete указатель, если он указывает на obj1 или obj2.

Я чувствую из этого вопроса и вашего предыдущего вопроса , что вы пришли с Java /C # фон.Лучше сначала почитать хорошую книгу по C ++, вы поймете, что большую часть времени вам не нужно new/delete.

1 голос
/ 23 августа 2011

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

0 голосов
/ 23 августа 2011

Я думаю, что пошел бы немного другим путем.

Как это:

test.h

class MyClass
{
public:
  MyClass();
  std::string name1;
  std::string name2;
  std::string type1;
  std::string type2;

  void method1(MyClass &obj1);
  void method2(MyClass &obj2);
}

test.cpp

MyClass mainObject; // default c-tor called automatically.

MyClass::MyClass()
{
}
void MyClass::method1(MyClass & obj1)
{
  //do stuff

  //we populate some of the MyClass variables
  mainObject.name1=obj1.name1;
  mainObject.type1=obj2.type1;
}
void MyClass::method2(MyClass & obj2)
{
  //do stuff

  //we populate more of the MyClass variables
  mainObject.name2=obj1.name2;
  mainObject.type2=obj2.type2;
}

Нет простого способа заполнить только часть вашего объекта, не указав, какие части.

Но, в противном случае, если вы не сделаете mainObject указателем, вам не нужно выделять для него место, это делается автоматически. (Но я должен возражать против использования глобалов, если они ДЕЙСТВИТЕЛЬНО не нужны!)

Эта реализация того, что, я думаю, вы пытаетесь сделать, полностью избавит вас от необходимости использования кучи, без необходимости нового / удаления.

0 голосов
/ 23 августа 2011

Из всех комментариев похоже, что вы действительно хотите следующее:

static MyClass mainObject; // Not a pointer. Local to test.cpp

void MyClass::method1()
{
  //do stuff
  mainObject=*this; // Make a copy of the last object modified.
}
void MyClass::method2()
{
  //do stuff
  mainObject=*this; // Make a copy of the last object modified.
}

Таким образом, независимо от того, вызываете ли вы foo.method1() или bar.method2, объект на левой стороне . копируется в mainObject. Никакой фанки указателя не требуется вообще, нет new и нет delete.

0 голосов
/ 23 августа 2011

Когда я должен удалить mainObject внутри test.cpp?

Когда он больше не используется.

Должен ли я создать деструктор дляклиент, чтобы удалить его?

Вы должны создать деструктор, только если некоторые ресурсы класса MyClass должны быть освобождены - это не так с показанным кодом.Тот, который вы должны освободить (= удалить), это mainObject.Но в любом случае method1 (..) и method2 (..) перезаписывают указатель mainObject, что приводит к висячему указателю (вы больше не можете добраться до объекта).

[EDIT]
ОтветитьВаш вопрос:

можно ли несколько раз удалить указатель c ++?

  1. Указатели обычно не выделяются новыми - только объекты, на которые они указывают.
  2. Если вы имеете в виду "может ли delete вызываться несколько раз по одному и тому же указателю?"ответ - нет и приведет к UB.delete для указателя, который равен нулю, определен и допустим.
0 голосов
/ 23 августа 2011

Всегда должен быть логический владелец любого ресурса, и этот владелец должен удалить ресурс.

В некоторых случаях имеет смысл иметь совместное владение, и именно это boost::shared_ptr и аналогичные решения.для.Последним, кто отказался от владения, является тот, кто удаляет ресурс.

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