我是否正确删除了这个?

时间:2010-04-06 19:35:39

标签: c++ memory-management delete-operator

我有一些结构:

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;
}

我知道这远非理想,远未完成。但是我想知道我是否以正确的方式删除了我的记忆(请不要告诉我如何正确地做到这一点。我正在试图弄清楚自己)。

the link这是对我来说非常重要的不同问题。

5 个答案:

答案 0 :(得分:4)

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会导致另一个析构函数调用不正确。你只需要释放内存。 e.g。

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

如果要分配原始内存以用于展示位置new,则直接使用分配功能更为常规。 e.g。

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

考虑做一些更简单的事情。这个块可以用一个更稳健的局部变量替换。

A tmp("tmp");

答案 1 :(得分:2)

如果您使用p = new[…]分配内存,那么您应该使用delete[] p [1] 取消分配,没有例外。

不要在tmp死后捣乱。

(Placement new不分配内存,析构函数不会修改new char[sizeof(A)],因此他们不会回答问题。)

[1]:您应将p声明为char*。或者将p投射到char*中的delete[]

答案 2 :(得分:0)

A的实例分配内存只需编写A* p = new A("tmp");。它将分配内存并调用构造函数。然后使用delete p;来调用析构函数并释放内存。我认为没有必要在您的案例中使用新的展示形式。

答案 3 :(得分:0)

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 [],因为您使用new []创建了内存。此外,在到达构造函数(在本例中为复制构造函数)之前,已经分配了内存,因此不需要再次分配它,这就是您在此处尝试执行的操作。

删除对象时,会自动调用析构函数(在本例中为~A),因此除非您使用的是新的展示位置,否则无需显式调用它。因此,删除中不需要显式删除为对象本身分配的内存,仅用于它拥有的成员。

复制构造函数应该只是复制正在复制的东西中的重要信息。 最后,这里的代码采用字符串:A a("a");,因此您需要一个字符串构造函数才能进行该调用:

A::A(const std::string& name)
{
   //Do stuff
}

答案 4 :(得分:0)

如果要为类中的指针分配内存,析构函数也应该释放(删除)内存:

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. 将链接移动到基类中 (首选是使用模板 节点的数据部分。}
  3. 基类将允许您使节点适应不同的数据类型:

    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::mapstd::list