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

配置で使用するためにrawメモリを割り当てる場合は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

でメモリを割り当てる場合は、例外なく[1]p = new[…]で割り当てを解除する必要があります。delete[] p

tmpそれが死んだ後、いじらないでください。

(配置新規はメモリを割り当てません。デストラクタはを変更new char[sizeof(A)]しないため、質問には入りません。)

[1]:pとして宣言する必要がありchar*ます。または、にキャストpします。char*delete[]

于 2010-04-06T19:41:03.053 に答える
0

A書き込みだけのインスタンスにメモリを割り当てる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[]?
}

はい、new []でメモリを作成したので、delete[]を使用する必要があります。さらに、コンストラクター(この場合はコピーコンストラクター)に到達する前に、メモリはすでに割り当てられているため、再度割り当てる必要はありません。これは、ここで実行しようとしているように見えます。

オブジェクトを削除すると、デストラクタ(この場合は〜A)が自動的に呼び出されるため、新しい配置を使用している場合を除き、明示的に呼び出す必要はありません。したがって、オブジェクト自体に割り当てられたメモリを明示的に削除する必要はなく、オブジェクトが所有するメンバーに対してのみ削除されます。

コピーコンストラクターは、コピーされるものから重要な情報を単にコピーする必要があります。最後に、ここのコードは文字列を取ります:A a("a");なので、その呼び出しを行うには文字列コンストラクターが必要です:

A::A(const std::string& name)
{
   //Do stuff
}
于 2010-04-06T19:49:54.613 に答える
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 に答える