我对好的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
- 指针的比较)是否可以用于这样的目的(例如,通过按值调用解析对象)还是有风险?当然,我假设原始对象总是比复制的对象更长。
谢谢!
答案 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)
};
在此,还应确保在允许复制之前完全分配共享内存。