1

最小ヒープの C++ コードを作成しようとしています。ポインターのベクトルを作成し、それらが適切に削除されていることを確認したいと考えています。

ポインターのベクトルを作成できますが、デフォルトのコンストラクターから無効な変換エラーが発生します。これはなぜですか?

また、メモリの問題がないことを確認するために、ユーザー定義のデストラクタを作成しようとしています。ただし、ポインターが割り当てられていないというエラーが発生する理由がわかりません。

#include <vector>
#include <iostream>

struct A
{
  A(int av, int bv):a(av),b(bv){}
  int a, b;
};

struct Heap
{
   Heap() : ptr(new std::vector<A*>()) {}  //WHY AM I GETTING AN ERROR FOR THE DEFAULT CONSTRUCTOR AND NOT THE CONSTRUCTOR BELOW?
   //ERROR: invalid conversion from ‘std::vector<A*, std::allocator<A*> >*’ to ‘long unsigned int’
   //ERROR: initializing argument 1 of ‘std::vector<_Tp, _Alloc>::vector(size_t, const _Tp&, const _Alloc&) [with _Tp = A*, _Alloc = std::allocator<A*>]’

   Heap(std::vector<A*> p) : ptr(p) {  //Works fine. 
       makeHeap();
   }

  ~Heap(){   //I DON'T UNDERSTAND WHY I AM GETTING A MEMORY ERROR HERE
        std::vector<A*>::iterator it;
    for(it=ptr.begin(); it<ptr.end(); ++it)
    {  
      delete *it;
      *it=NULL;
    }
  }//ERROR:  malloc pointer being freed was not allocated  

  void makeHeap()
  {  //some code  }

  std::vector<A*> ptr;
  std::vector<int> heapLoc;
};


int main()
{
  A a0(2,5), a1(4,2);  
  std::vector<A*> aArray;  
  aArray.push_back(&a0);
  aArray.push_back(&a1);

  Heap h(aArray);

  return 0;

}
4

3 に答える 3

2

ptrベクトルへのポインタではなく、ポインタのベクトルです。newしたがって、ヒープ上に構築してアドレスを保存するために使用することはできません。

代わりに、次のように構成します。

Heap() : ptr() {}

これは のデフォルト コンストラクターと呼ばれますptr。つまり、ポインターの空のベクターを作成します。ptr実際にはポインターではないため、 の名前を変更することも検討する必要があります。


あなたのデストラクタについて(Dietmarはその間に回答を投稿し、彼の前にCameronはそれを説明するコメントを投稿しました(+1)が、完全を期すために):ベクトルに保存するポインタスタック上に作成したオブジェクトのアドレスを参照します。具体的には、ここで作成するオブジェクト:

int main()
{
  A a0(2,5), a1(4,2);  // <-- automatic storage, so they
                       //     will be deallocated automatically
  /* ... */
}

Heapオブジェクトがそれ自身のオブジェクトを担当するようにしたい場合は、デストラクタが削除できるヒープ上にオブジェクトを作成するコンストラクタを持たせる必要があります。Heapこれを行う 1 つの方法は、次のように のコピー コンストラクターを定義することです。

Heap(const std::vector<A*> &p) : ptr() {
  std::vector<A*>::const_iterator it(p.begin());
  for ( ; it != p.end() ; ++it)
    ptr.push_back(new A(**it));
}

デストラクタはそのまま使用できますが、for ループの!=代わりに使用することもできます。<

~Heap() {
   std::vector<A*>::iterator it;
   for(it=ptr.begin(); it != ptr.end(); ++it)
   {  
     delete *it;
     *it=NULL;
   }

最後に、(オブジェクトのベクトルではなく) ポインターのベクトルが本当に必要かどうかはわかりませんが、必要だと思われる場合は、スマート ポインターの使用を検討してください (たとえば、C++11 の offersを使用すると、回避std::unique_ptrするために a を定義できます)。std::vector<std::unique_ptr<A>>割り当て関連の問題の多く)。

于 2012-11-25T01:01:55.797 に答える
2

以下のコンストラクターではなく、デフォルトのコンストラクターでエラーが発生するのはなぜですか?

ptr(new std::vector<A*>())

これは、 operatorがそれ自体ではなくへのポインターnew返すためです。aをオブジェクトとして宣言しているので、部分全体を単純に削除する必要があります。 はコンパイラによって正しく初期化されます。std::vectorvectorvectorptr(...)ptr

より現代的なアプローチはunique_ptr<T>、「生の」ポインターの代わりに使用することです。これにより、 が破棄されたときに自動的に適切な破棄が保証vector<unique_ptr<T>>されます。

于 2012-11-25T01:03:26.673 に答える
1

人々はそれを指摘していないので:Heapスタックへのポインタ、つまりフリーストアに割り当てられていないオブジェクトを破棄すると(「ヒープ」と言おうとしましたが、これは不必要な混乱を引き起こす可能性があります...)おかしな振る舞いもします。このアプローチ全体は、最初から運命づけられています。自分が何をしているのかを本当に理解していない限り、生のポインターのコンテナーを使用しないでください(それでも、生のポインタのコンテナを使用しない方がおそらく最善です)

于 2012-11-25T01:06:22.493 に答える