记住只能管理共享内存的原始对象

时间:2015-07-21 10:17:58

标签: c++ destructor default-copy-constructor

我对好的C ++风格有疑问: 我想写一个类“MyClass”,它有一个或一些指针作为成员,MyClass能够为这个指针分配内存。我想使用隐式给出default-copy-constructor(以及default-assignement-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 - 指针的比较)是否可以用于这样的目的(例如,通过按值调用解析对象)还是有风险?当然,我假设原始对象总是比复制的对象更长。

谢谢!

2 个答案:

答案 0 :(得分:1)

不,这是一个坏主意。如果指针由多个实例共享,那么要解除分配的指针应该是最后一个死亡,而不是原始实例。这在某种意义上是不同的,即原始的可能不会死亡,这将导致所有其他人指向垃圾。即使你认为它是最后一个死的,你需要意识到一个类的内部运作不应该依赖于外部假设。也就是说,该类无法保证其实现的其余部分如何管理其生命周期,因此它不应该做出假设。





在这种情况下你应该跟踪对您数据的引用。基本思路是跟踪你所拥有的课程副本数量。一旦计数达到零,你就可以释放那个记忆;最后一份副本刚刚去世。幸运的是, STL已经提供了这样的实施。这些被称为智能指针。还有其他一些,例如 std :: unique_ptr ,它通过确保相反数据仅由单个实例拥有。




答案 1 :(得分: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)

};

在此,还应确保在允许复制之前完全分配共享内存。