2017-01-04 4 views
0

ABCクラスを作成し、その3つのオブジェクトを通常の割り当ておよびコピーコンストラクタで作成しました。今は彼らはptrの同じメモリアドレスを使用しています。他のオブジェクトでmomeryが使用されているときにptrを削除しない

これらのオブジェクトが削除されると、最初のオブジェクトが削除されてスコープから外れることを意味しますが、2番目にはメモリが既に削除されているというエラーが発生します。 これは問題ありません。私は理解している。

私は他のオブジェクトを使用しているときに、メモリを削除したくない、ということをやりたい
#include<iostream> 
using namespace std; 

class ABC 
{ 
    private: 
     int a; 
     int *ptr; 

    public: 
     ABC();      // Simple constructor. 
     ABC(int a, int b);   // Parameterized constructor. 
     ABC(const ABC &obj);  // Copy constructor. 
     ~ABC();      // Destructor. 
     void display();    // Display. 
     ABC& operator=(const ABC &obj); // Operator Overload. 
}; 


ABC::ABC() 
{ 

} 


ABC::ABC(int a, int b) 
{ 
    cout << "Parameterized constructor" << endl; 
    // allocate memory for the pointer; 
    this->a = a; 
    ptr = new int; 
    ptr = &b; 
} 


ABC::ABC(const ABC &obj) 
{ 
    cout << "Copy constructor" << endl; 
    a = obj.a; 
    //ptr = new int; 
    //*ptr = *obj.ptr; // copy the value 
    ptr = obj.ptr; 
} 


ABC& ABC :: operator=(const ABC &obj) 
{ 
    cout <<"Assignemnt operator overload"<<endl; 
    this->a = obj.a; 
    this->ptr = obj.ptr; 
    return *this; 
} 


ABC::~ABC(void) 
{ 
    cout << "Freeing memory!" << endl; 
    delete ptr; 
} 


void ABC::display() { 
    cout << "a value = : " << a <<endl; 
    cout << "ptr value = : " << ptr <<endl; 
    cout << "*ptr value = : " << *ptr <<endl; 
} 


int main() 
{ 
    // Normal. 
    ABC obj1(1, 2); 
    cout << "Point Obj1 value = : "<<endl; 
    obj1.display(); 

    cout<<"\n\n"; 
    // Assignment. 
    ABC obj2; 
    obj2 = obj1; 
    cout << "Point Obj2 value = : "<<endl; 
    obj2.display(); 

    cout<<"\n\n"; 
    // Copy constructor. 
    ABC obj3(obj1); 
    cout << "Point Obj3 value = : "<<endl; 
    obj3.display(); 

    return 0; 
} 

。どのようにスマートポインタでこれを処理するには、私はビルドせん断ポインタで行うしたくないです。 Smart Pointerクラスを作成し、他のオブジェクトが同じメモリを使用しているときにptr参照カウントを増やしたい。しかし、どのようにするか分からない。

class SmartPointer 
{ 

    public: 
     int *ptr; 
     int ref; 
     SmartPointer(); 
     SmartPointer(int *p); 
     int& operator *(); 
     ~SmartPointer(); 
}; 

SmartPointer::SmartPointer() 
{ 
    cout<<"SmartPointerInitilaize default"<<endl; 
    ref = 1; 
} 


SmartPointer::SmartPointer(int *p) 
{ 
    cout<<"SmartPointerInitilaize para"<<endl; 
    ptr = p; 
    ref = 1; 
} 

int& SmartPointer:: operator *() 
{ 
    return *ptr; 
} 

SmartPointer::~SmartPointer() 
{ 

    cout<<"SmartPointer De-Initilaize"<<endl; 
    //delete ptr; 
} 
+1

私はなぜあなたが再びホイールを発明したいのかわかりません。 まず最初に refカウンタが静的になる必要があります。 2番目のコンストラクタでインクリメントし、デストラクタでデクリメントします。 thrid、デストラクタでrefカウンタが0になると、あなたのpinterを解放する必要があります。 良い一日をお過ごしください – jamek

+1

'static'参照カウンタを追加し、マルチスレッド環境で使用する場合はmutexなどでロックすることを忘れないでください。 – Unimportant

+0

カウントに 'static'を使うのは誰ですか?コンストラクタを代入またはコピーしてオブジェクトが作成されているときに、リフカウントを増やしたいということです。 –

答えて

2

std::shared_ptrを基本的に実行します。しかし、教育上の目的やその仕組みを理解するのは非常に難しいので、通常は行うべきではありません:

1)refカウントは、渡されたポインタデータの一部である必要がありますすべての "リンクされた" SmartPointerインスタンスによって共有されます。

2)参照カウントを増やすには、コピーコンストラクタ/代入演算子を定義する必要があります。また、デストラクタでは、refcountを減らし、ゼロの場合はポインタ(および余分なデータ)を削除します。

例:これは非常に単純化されていることを

class SmartPointer 
{ 

    struct Data { 
     Data(int *p) 
      : ptr(p) 
      , ref(1) 
     {} 
     ~Data() {Release();} 
     void Acquire() { 
      ++ref; 
     } 
     void Release() { 
      if (!--ref) { delete ptr; delete this; } 
     } 
     int *ptr; 
     int ref; 
    }; 

     Data *data; 
    public: 
     SmartPointer() 
      : data(new Data(NULL)) 
     {} 
     SmartPointer(int *p) 
      : data(new Data(p)) 
     {} 
     SmartPointer(const SmartPointer& x) 
      : data(x.data) 
     { data->Acquire(); } 
     SmartPointer& operator =(const SmartPointer& x) 
     { 
      if (this != &x) { 
       data->Release(); 
       data = x.data; 
       data->Acquire(); 
      } 
     } 
     int& operator *() { return *data->ptr; } 
     ~SmartPointer() { data->Release(); } 
}; 

注意(例えばスレッドセーフではありません)、単に基本的な考え方。

実際のstdまたはboostのshared_ptrは、はるかに複雑です(テンプレート化され、型消去などを伴うカスタム・ディターターをサポートしています)。

+0

私の悪い!削除されました。 – MSalters

+0

'data(新しいデータ(p))'私はこれを取得していません。 –

+0

これは、ポインタとスマートポインタ**のすべてのインスタンス間で共有される参照カウント**を含むデータを作成します。これは、共有ポインタが正しく動作するために不可欠です(すべての共有インスタンスのすべての参照カウントが同じになるように)。 – axalis

1

ABCコンストラクタを呼び出しているときはいつでもSmartPointer

class SmartPointer{ 

public: 
    int *ptr; 
    int ref; 
    int shared_level; 
    SmartPointer(); 
    SmartPointer(int *p); 
    int& operator *(); 
    ~SmartPointer(); 
}; 

をshared_level整数を追加します。 shared_levelを1増分してください。deconstructorの呼び出し時に、1を減らしてください。 SmartPointer-> shared_levelの値をチェックしています。それが1の場合は、ポインタを削除してください。

注:複数のスレッドでアクセスしたい場合は、sharePointerのロックをよりよく使用してください。

+0

このようにして、複数のインスタンス間でコピーされた場合、 'ref'または' shared_level'の値が離れていきます。したがって、すべてのSmartPointerインスタンス間で参照データを共有する必要があります。あなたは何とか2つのインスタンス間でrefを同期させておくことができますが、デストラクタでも各インスタンスは独自の値を持ちます(両方のインスタンスで2になります)。インスタンス)、ポインタは決して解放されません。 – axalis

+0

各インスタンス_destructorは(両方のインスタンスのために2になります)、独自の値を持つことになります、とだけ(約他のすべてのインスタンスを知らない)を1回デクリメントされますので、ポインタがfreed._ことはありませんでしょう デコンストラクタ各オブジェクト(ABC)に対して呼び出されます。 R8? – ban

+0

はい、それぞれがref count = 2を持ち、自身のコピーを1に減らします。つまり、ポインタを解放しません。両方とも1であれば、両方とも無料になります(=重複フリー=セグメンテーション)。 – axalis

関連する問題