3

我有一些结构:

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

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

这是指向不同问题的链接,这对我来说非常重要。

4

5 回答 5

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 是不正确的,这将导致另一个析构函数调用。你只需要释放内存。例如

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");
于 2010-04-06T19:40:39.403 回答
2

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

tmp死了以后不要乱来。

(放置 new 不分配内存,析构函数不会修改new char[sizeof(A)],所以他们不会进入问题。)

[1]:您应该声明pchar*. 或强制p转换为char*in delete[]

于 2010-04-06T19:41:03.053 回答
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. 将链接移动到基类中(首选使用模板作为节点的数据部分。}

基类将允许您使节点适应不同的数据类型:

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

于 2010-04-06T20:06:07.940 回答
0

分配内存,例如Ajust write A* p = new A("tmp");。它将分配内存并调用构造函数。然后用于delete p;调用析构函数并释放内存。在您的情况下,我看不出有任何需要使用 new 的放置形式。

于 2010-04-06T19:41:13.223 回答
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
}
于 2010-04-06T19:49:54.613 回答