Я удаляю это правильно? - PullRequest
3 голосов
/ 06 апреля 2010

У меня есть структура:

struct A
{
 const char* name_;
 A* left_;
 A* right_;
 A(const char* name):name_(name),
      left_(nullptr),
      right_(nullptr){}
 A(const A&);
 //A(const A*);//ToDo
 A& operator=(const A&);
 ~A()
 {
  /*ToDo*/
 };
};
/*Just to compile*/
A& A::operator=(const A& pattern)
{

 //check for self-assignment
 if (this != &pattern) 
 {
  void* p = new char[sizeof(A)];
 }
 return *this;
}

A::A(const A& pat)
{
 void* p = new char[sizeof(A)];
 A* tmp = new (p) A("tmp");
 tmp->~A();
 delete tmp;//I WONDER IF HERE I SHOULD USE DIFFERENT delete[]?
}

int _tmain(int argc, _TCHAR* argv[])
{
 A a("a");
 A b = a;
 cin.get();
 return 0;
}

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

Это ссылка на другой вопрос, который действительно важен для меня.

Ответы [ 5 ]

4 голосов
/ 06 апреля 2010
void* p = new char[sizeof(A)];
A* tmp = new (p) A("tmp");
tmp->~A();
delete tmp;//I WONDER IF HERE I SHOULD USE DIFFERENT delete[]?

Нет. Вы уже вызвали деструктор, поэтому неправильно вызывать delete, что вызовет другой вызов деструктора. Вам нужно только освободить память. например,

delete[] static_cast<char*>(p);

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

void* p = ::operator new[](sizeof(A));
A* tmp = new (p) A("tmp");
tmp->~A();
::operator delete[](p);

Хотя попробуйте сделать что-нибудь попроще. Этот блок может быть заменен одной локальной переменной, которая будет более устойчивой.

A tmp("tmp");
2 голосов
/ 06 апреля 2010

Если вы выделяете память с помощью p = new[…], то вам следует освободить ее с помощью delete[] p [1] , без исключений.

Не связывайтесь с tmp после его смерти.

(Размещение нового не выделяет память, деструктор не изменит new char[sizeof(A)], поэтому они не входят в вопрос.)

[1]: Вы должны объявить p как char*. Или приведите p к char* в delete[].

0 голосов
/ 07 апреля 2010

Если вы выделяете память для указателя в классе, деструктор также должен освободить (удалить) память:

class Node
{
  char * name_;
  Node * p_left;
  Node * p_right;

  Node(const char * new_name)
  : name_(NULL), p_left(NULL), p_right(NULL)
  {
    size_t size = strlen(new_name);
    name_ = new char [size + 1]; // + 1 for terminating null
  }
  ~Node()
  {
     delete[] name_;
  }
};

Я настоятельно рекомендую:

  1. Использование std::string вместо char * для текста.
  2. Переместить ссылки в базовый класс (предпочтительнее использовать шаблон для раздел данных узла.}

Базовый класс позволит вам адаптировать узел к различным типам данных:

struct Node
{
    Node * p_left;
    Node * p_right;
};

struct Name_Node
: public Node
{
  std::string name;
};

struct Integer_Node
: public Node
{
  int value;
};

OTOH, вы можете использовать std::map или std::list после этого упражнения.

0 голосов
/ 06 апреля 2010
A::A(const A& pat)
{
 void* p = new char[sizeof(A)];
 A* tmp = new (p) A("tmp");
 tmp->~A();
 delete tmp;//I WONDER IF HERE I SHOULD USE DIFFERENT delete[]?
}

Да, вы должны использовать delete [], так как вы создали память с новым []. Более того, до того, как вы достигнете конструктора (в данном случае конструктора копирования), память уже была выделена, поэтому нет необходимости выделять ее снова, как вы, похоже, пытаетесь здесь сделать.

Когда вы удаляете объект, деструктор (в данном случае ~ A) вызывается автоматически, поэтому нет необходимости явно вызывать его, если вы не используете новое размещение. Таким образом, при удалении нет необходимости явно удалять память, выделенную для самого объекта, только для принадлежащих ему элементов.

Конструктор копирования должен просто скопировать важную информацию из копируемой вещи. Наконец, код здесь принимает строку: A a("a");, поэтому вам понадобится строковой конструктор, чтобы сделать этот вызов:

A::A(const std::string& name)
{
   //Do stuff
}
0 голосов
/ 06 апреля 2010

Чтобы выделить память для экземпляра A, просто напишите A* p = new A("tmp");.Он выделит память и вызовет конструктор.Затем используйте delete p; для вызова деструктора и освобождения памяти.Я не вижу необходимости использовать форму размещения новых в вашем случае.

...