0

私は小さなソフトウェアをプログラミングして、ヒープ上に新しいオブジェクトを作成したいと考えていました。したがって、クラスメンバー関数では

void  gShop::CreateCustomer(int type, int number)
    {
    vSlot[number] = new gCustopmer(type);
    vSlot[number]->itsContactToShop=itsShopNumber;
    vSlot[number]->itsNumber=number;
    }

ここで、vSlot は顧客オブジェクトへのポインターのベクトルです。私は本質的に(ここでは省略された)クラスgShopを持っています:

class gShop : public gBranch
   {
   public:
       gShop(): vSlot(100){}
      ~gShop(){}   

       std::vector <gCustomer*>   vSlot;
       ...
   }

そして主に、メンバー関数を呼び出して新しい顧客を作成します..

  vShop[0].CreateCustomer(TYPE_M20, 1);
  vShop[0].CreateCustomer(TYPE_F40, **2**);//EDIT:typo previously here. I intend to create customers by reading a file later on.

  std::cout<< "1" << vShop[0].vSlot[1]->itsTypeString << std::endl;
  std::cout<< "2" << vShop[0].vSlot[2]->itsTypeString << std::endl;

「ヒープ」に「新しい」2つのオブジェクトを作成したことを知っています(用語を正しく処理すれば、正式な教育を受けていないプログラミングは初めてで申し訳ありません)。また、そのオブジェクトへの2つのポインターがベクトル内に格納されていますオブジェクトショップ[0]。

私の質問は、新しいものごとに削除があるということわざを聞いたことです。このオブジェクトをどこで削除する必要がありますか? プログラムで作成したショップや顧客オブジェクトを削除するつもりはありません。

第二に、メモリ リークを引き起こさないという点で、このコードは今のところ大丈夫ですか? メンバー関数クラス内で新しいオブジェクトを作成したことを少し心配しているので、gShop へのデストラクタで削除を実装し、ポインターを NULL に設定する必要があります - 理論的なケースでは、shop[0] を削除する必要があります。 ?

どうもありがとう。

4

4 に答える 4

3

コードを記述した方法で、各要素gShopを反復処理するためにデストラクタの実装を拡張する必要があります。メモリ リークを防ぐためにこの方法で管理する必要があるメモリがあるため、 Rule of Threeに従う必要もあります。そのため、コピーの作成中にも何かを行う必要があり (ディープ コピー)、代入演算子に対して何かを行う必要があります (コピーしようとしている をクリーンアップし、ディープ コピーを実行します)。vector<> vSlotdeletevector<>

代わりにスマート ポインターを使用することで、これらの問題を回避し、オブジェクトが既定のデストラクター、コピー コンストラクター、代入演算子を使用できるようにすることができます。例えば:

    std::vector<std::shared_ptr<gCustomer>> vSlot;

で要素を作成する場合はvSlot、次を使用できますmake_shared()

    vSlot[number] = std::make_shared<gCustopmer>(type);

メモリへの参照がなくなると、スマート ポインタがメモリを削除します。C++.11 を利用できない場合は、boost::shared_ptr代わりに使用できます。

スマート ポインターは、コピーgShop元のポインターと同じポインターを共有するようにgShopします。deleteスマート ポインターは、同じメモリ上に複数の呼び出しが存在しないため、この状況を問題なくします。ただし、ディープ コピー セマンティクスが必要な場合は、独自のコピー コンストラクターと代入演算子を実装してディープ コピーを作成する必要があります。

スマート ポインターのように自動的にクリーンアップするものが必要であるが、デフォルトのコピー コンストラクターとデフォルトの代入演算子を使用してディープ コピーを提供する場合は、boost::optional.

バージョン 4.4 以降を使用している場合、またはGNU 拡張機能が必要ない場合は、 g++C++.11 機能を有効にできるはずです。4.7 以降の場合、オプションはまたはです。-std=gnu++0x-std=c++0xg++-std=gnu++11-std=c++11

于 2013-10-07T23:10:48.760 に答える
0

はい、ヒープから割り当てられたメモリはすべて解放する必要があります! 「新規」では、gCustomer のサイズであるヒープからメモリを割り当てています。メモリの割り当てを解除するのに適した場所は、デストラクタにあります: ~gShop() メモリ リークは、メモリの割り当てを解除しないと発生しますが、プログラムを閉じるとすべてのメモリが自動的に解放されます。

于 2013-10-07T23:12:05.437 に答える
0

オブジェクトを作成するたびnewに、メモリの一部がヒープから取得されます。このメモリと通信する唯一の方法は、 から取得したポインタを使用することですnew。そのポインターで使用するdeleteと、メモリが解放され、他の目的に使用される可能性があります。したがって、ポインターを失うと、メモリリークが発生します。
あなたのコードでは、正しい方法は次のとおりです
。null ポインターを持つベクトルから始めます。正確な位置にオブジェクトを作成するときは、ポインターを確認してください。null でない場合は、既にオブジェクトがあり、それを削除する必要があります (または、エラーをスローする可能性があります)。

void  gShop::CreateCustomer(int type, int number)
{
    if(vSlot[number] != 0) {
         delete vSlot[number];
         vSlot[number] = 0;
    }
    vSlot[number] = new gCustopmer(type);
    vSlot[number]->itsContactToShop=itsShopNumber;
    vSlot[number]->itsNumber=number;
}

ベクターが破棄されたら、ベクター内のすべてのメモリを解放する必要があります。したがって、デストラクタは次のようになります。

gShop::~gShop() {
    for(int i = 0; i < (int)vSlot.size(); ++i) {
          delete vSlot[i];
    }
}
于 2013-10-07T23:14:18.400 に答える