2

コピー コンストラクタ、コピー代入演算子、およびデストラクタがどのように機能するかを理解するために、次のダミー クラスを作成しました。

#include <string>
#include <iostream>

class Box {

  public:
    // default constructor
    Box(int i=10,const std::string &t=std::string()) : a(i),s(new std::string(t)) {}
    // copy constructor
    Box(const Box &other) { a=other.a; s=new std::string(*other.s); }
    // copy assignment operator
    Box &operator=(const Box &other) { a=other.a; s=new std::string(*other.s); }
    // destructor
    ~Box() { std::cout<<"running destructor num. "<<++counter<<std::endl; }
    int get_int() { return a; }
    std::string &get_string() { return *s; }
  private:
    int a;
    std::string *s;
    static int counter;

};

int Box::counter=0;

コードでこのクラス型を使用して、それがどのように機能するかをテストしていますが、組み込みのポインター型のメンバーを持つオブジェクトを破棄する場合の影響について考えていました。

#include "Box.h"

using namespace std;

int main()
{
  Box b1;
  Box b2(2,"hello");
  cout<<b1.get_int()<<" "<<b1.get_string()<<endl;
  cout<<b2.get_int()<<" "<<b2.get_string()<<endl;
  Box b3=b1;
  Box b4(b2);  
  cout<<b3.get_int()<<" "<<b3.get_string()<<endl;
  cout<<b4.get_int()<<" "<<b4.get_string()<<endl;
  b1=b4;
  cout<<endl;
  cout<<b1.get_int()<<" "<<b1.get_string()<<endl; 
  {
    Box b5;
  }  // exit local scope,b5 is destroyed but string on the heap
     // pointed to by b5.s is not freed (memory leak)
  cout<<"exiting program"<<endl;
}

このポインターはコンストラクターで初期化され、フリー ストア上の (常に新しい) 動的に割り当てられたメモリを指します。したがって、デストラクタが呼び出されると、破棄されるオブジェクトのメンバーが逆の順序で破棄されます。この場合、int オブジェクトとポインター オブジェクトのみが破棄され、最終的にメモリ リークが発生します (ヒープ上の文字列は解放されません)。

また、このコピー代入演算子を定義すると、オブジェクトを代入するたびにメモリ リークが発生しますか (ポインターはヒープ上の新しいオブジェクトを指し、前者は失われますよね?)。

4

3 に答える 3

4

new を呼び出すたびに、それを削除する必要があります (共有ポインターを除く)。

したがって、デストラクタで文字列を削除する必要があります。

代入演算子は既存のインスタンスで機能するため、既に s を作成しており、s の新しい文字列を作成する必要はありません。

デストラクタはそのメンバーを破棄します。ポインタは int に似ているため、ポインタが指しているオブジェクトではなく、アドレスを保持する変数のみが破棄されます。

そうです、各オブジェクトでメモリリークが発生し、クラスを設計した方法で代入演算子を使用するたびにメモリリークが発生します。

于 2015-09-09T10:57:09.870 に答える