有一个类
class A
{
public:
    A();
    ~A();
    BYTE* GetData();
    void SetData(BYTE* data);
    void Clear();
    A& operator =(A &a);
protected:
    BYTE* m_pbData;
}A& A:: operator=(A &a)
{
   Clear(); //这里有一个问题
   SetData(a.GetData());
   return *this;
}void A::Clear()
{
  try 
  {
     delete m_pbData;
  }
  catch(...)
  {
     //do nothing
  }
}它的析构函数
A::~A()
{
   Clear(); //这里也有一个问题
}在另一个对象中调用的时候A a = GetA();下面是GetA()的实现
A GetA()
{
    A a;
    BYTE *pb = new BYTE[10];
    a.SetData(pb);
    return a;
}在 
A a = GetA();
这句执行的时候,由于在GetA()内部 return a的时候 a的析构函数被执行,所以
在赋值的时候,也就是执行重载的 = 的时候,会出错,因为m_pbData已经被delete了。关键的问题出在A::Clear()
在Clear的时候,Clear并不知道m_pbData是否被其它的对象引用,请教高手,怎样
解决这个问题?

解决方案 »

  1.   

    关键不在Clear上,你如果要从GetA中返回一个类对象,应该返回一个指针,
    也就是要用new操作符生成一个对象,然后返回。
    如果申请的是一个变量,那么在函数执行完毕后,这个对象就不存在了。外面再次
    使用时肯定是非法对象
      

  2.   

    可以利用com的方法。
    进行引用计数,当引用计数为0时删除即可。
      

  3.   

    你应该加一个Attach函数和Detach函数,如果引用外部的对象,就Attach,之后在Detach中把引用的成员赋空,二者成对出现,这样就不会在析构函数中出现问题了。
    SetData(BYTE* data);函数要把m_pbData new出一个空间,在把data的数据拷贝到m_pbData里,这样符合逻辑否则的话析构函数就索性不要管它的删除
      

  4.   

    你如果想在各个类中共享指向的数据,必须为buffer配上一个计数器,然后把它和buffer一起封装到一个小类中中,然后再你的类中定义一个这样的对象。当它第一次被引用时,counter为1,然后每执行一次copy构造或者copy赋值,就加1,析构时,如果计算器大于1,则什么也不错,只是减1,如果等于1才删除buffer。但这样虽然节约空间,但实在太复杂,搞不好还弄出内存错误来。如果需要共享的数据量不是很大,我还是建议每个对象维护自己的buffer,copy构造或者copy赋值时进行深拷贝(拷贝内容),而不是拷贝指针。当然,还是需要在对象构造时把buffer置为空,然后需要时再分配;而每一次删除后也置为空。对于析构函数,如果判断buffer已经空了,则什么也不做。GetData应该返回类的成员变量,而不是函数局部变量,那样太危险。
    还有,好像你的buffer也不知道个长度,如果做深拷贝,如何进行?
      

  5.   

    GetA() 里面的  A a 是局部变量,函数结束的时候,a的生存期也就结束了
    出错不是因为_pbData已经被delete,而是 a 就已经不存在了,
      

  6.   

    首先应该确定
    A a;
    BYTE *pb = new BYTE[10];
    a.SetData(pb);
    return a;
    中a是一个局部变量,函数返回的时候就会被释放掉。
    要返回就应该使用new在堆里生长一个新的对象。使用引用计数也应该用new生成对象,否则会造成内存泄漏
      

  7.   

    写掉了
    BYTE* A::GetData()
    {
        return m_pbData;
    }另外,GetA()中的代码不应该改变,因为我需要的是这样一个对象A,而不是一个简单的内存块。此外,录GetA中的a对象释放掉之前系统会将它复制一份作为返回值,请大家不要忽略了这件事情。还有,A和CString很相像,但是我不想在 A 中开辟新内存块,而只是保留一个引用,并对引用的这块内存进行管理,这点和CString不太一样。
      

  8.   

    很简单的问题m_pbData仅仅是一个指针成员,他所指向的空间不由类内部申请和释放,所以析沟函数没必要管他
      

  9.   

    这个类的一个目的,就是要对m_pbData进行管理。用拷贝构造函数还不能完全达到这种目的。