1

良い C++ スタイルについて質問があります。メンバとして 1 つまたはいくつかのポインタを持つクラス "MyClass" を書きたいのですが、MyClass はこのポインタにメモリを割り当てることができます。暗黙的な Give default-copy-constructor (および default-assignment-operator) を使用して MyClass のインスタンスをコピーし、ポインターのみがコピーされ、新しいオブジェクトが初期オブジェクトが持つデータを共有するようにしたいと考えています。割り当てられます。

私の考えは、コピーされたオブジェクト (コピー コンストラクターまたは代入演算子で作成されたもの) がメモリを解放する (およびメンバー ポインターにメモリを割り当てる) ことを禁止することでした。コピーされたオブジェクトと元のオブジェクト (コンストラクターによって作成された) を区別するために、次のコードを使用します。

class MyClass
{
public:
       MyClass(): originalPtr(this) { data = new char[100000]; }
       ~MyClass() { if(originalPtr == this) delete[] data; }
private:
       MyClass *originalPtr;
       char *data; // shared data (not copiable)
       char otherFeatures[10]; // individual data (copiable)
};

このソリューション ( this-pointer との比較を使用) は、そのような目的 (たとえば、値による呼び出しによるオブジェクトの解析) に適したスタイルでしょうか?それともリスクがありますか? もちろん、元のオブジェクトはコピーされたオブジェクトよりも常に長生きすると思います。

ありがとうございました!

4

2 に答える 2

1

No, this is a bad idea. If the pointers are shared by several instances, than the one to deallocate should be the last one to die, not the original one. This differs in the sense that the original one might not be the one to die, which would cause all others to be pointing at garbage. Even though you assume that it's the last one to die, you need to realise that the inner workings of a class should not rely on external assumptions. That is, the class has no guarantees on how its life span is managed by the rest of the implementation, so it shouldn't make assumptions.

In this situation you should track references to your data. The basic idea is to keep track of how many copies of the class you have. As soon as that count reaches zero, you are free to release that memory; the last copy has just died. Fortunately for you, STL already provides such an implementation. These are known as Smart Pointers. There are others, such as std::unique_ptr, which makes the opposite by ensuring that the data is owned only by a single instance.

于 2015-07-21T10:27:59.427 に答える
0

わかりました、元のオブジェクトが最終的に死なない一般的なケースを想定します。インスタンスを数えるだけのアイデアが好きです。たとえば、次のような概念を使用できます。

class MyClass
{
public:
   MyClass(): countOfInstances(new int())
   {
       ++*countOfInstances;
       data = new char[100000];
   }

   ~MyClass()
   {
       --*countOfInstances;
       if(!countOfInstances)
       {
           delete[] data;
           delete countOfInstances;
       }
   }    

   MyClass(const MyClass &other) // analogous for the assignment operator
   {
       countOfInstances = other.countOfInstances;
       data = other.data;
       otherFeatures = other.otherFeatures;
       ++*countOfInstances;
   }

private:
   int *countOfInstances;
   char *data; // shared data (not copiable)
   char otherFeatures; // individual data (copiable)

};

ここで、コピーの作成を許可する前に、共有メモリが完全に割り当てられていることも確認する必要があります。

于 2015-07-21T11:11:55.443 に答える