5

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

4

3 に答える 3

8

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

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

生メモリ ポインターを使用するクラスでは、常にコピー コンストラクターと 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= private を作成します。これが「ドアをロックする」ソリューションです。シンプルで効果的ですが、過保護になることもあります。

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

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

  • 生の char ポインターの代わりに文字列クラスを使用する
  • 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)
  {
  }
};
于 2008-10-19T07:51:24.170 に答える
5

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

于 2008-10-19T07:10:45.470 に答える
2

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

于 2008-10-19T07:48:03.133 に答える