質問

構造体" s"があるとしますintポインターメンバー変数" i"を使用します。 sのデフォルトコンストラクターでiのヒープにメモリを割り当てます。後でコードの他の部分で、値によってsのインスタンスを関数に渡します。ここで浅いコピーをしていますか?コピーコンストラクタまたは代入演算子、またはsの何かを実装しなかったと仮定します。デフォルトコンストラクタだけです。

役に立ちましたか?

解決

@ [don.neufeld.myopenid.com]が言ったことをフォローアップするために、それは浅いコピーであるだけでなく、メモリリークまたは宙ぶらりんのポインターのいずれかです(選択してください)。

// memory leak (note that the pointer is never deleted)
class A
{
  B *_b;
  public:
  A()
  : _b(new B)
  {
  }
};

// dangling ptr (who deletes the instance?)
class A
{
  B *_b;
  public:
  A()
  ... (same as above)

  ~A()
  {
    delete _b;
  }
};

これを解決するには、いくつかの方法があります。

rawメモリーポインターを使用するクラスでは、常にコピーコンストラクターとoperator =を実装します。

class A
{
  B *_b;
  public:
  A()
  ... (same as above)

  ~A()
  ...

  A(const A &rhs)
  : _b(new B(rhs._b))
  {
  }

  A &operator=(const A &rhs)
  {
    B *b=new B(rhs._b);
    delete _b;
    _b=b;
    return *this;
};

言うまでもなく、これは大きな苦痛であり、正しさを得るにはかなりの微妙な点があります。私はここでそれをやったかどうかも完全にはわかりませんし、数回やったこともあります。すべてのメンバーをコピーする必要があることを忘れないでください-後で新しいメンバーを追加する場合は、それらを追加することも忘れないでください!

コピーコンストラクターとoperator =をクラスでプライベートにします。これは「ドアをロックする」です。溶液。シンプルで効果的ですが、保護が強すぎる場合があります。

class A : public boost::noncopyable
{
  ...
};

生のポインタを使用しないでください。これは簡単で効果的です。ここには多くのオプションがあります:

  • 生の文字ポインタの代わりに文字列クラスを使用する
  • std :: auto_ptr、boost :: shared_ptr、boost :: scoped_ptrなどを使用

例:

// uses shared_ptr - note that you don't need a copy constructor or op= - 
// shared_ptr uses reference counting so the _b instance is shared and only
// deleted when the last reference is gone - admire the simplicity!
// it is almost exactly the same as the "memory leak" version, but there is no leak
class A
{
  boost::shared_ptr<B> _b;
  public:
  A()
  : _b(new B)
  {
  }
};

他のヒント

はい、それは浅いコピーです。 sの2つのコピー(呼び出し側に1つ、パラメーターとしてスタックに1つ)があり、それぞれに同じメモリブロックへのポインターが含まれています。

s 構造体の2つのコピーがあり、それぞれに独自の i ポインターがありますが、両方の i ポインターにはメモリ内の同じアドレスを指す同じ値-そう、それは浅いコピーになります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top