2010-08-06 27 views
7

我有一个使用了引用计数机制的类。当参考计数下降到零时,通过调用delete this最终销毁此类的对象。我的问题是:我可以在delete this之后使用本地堆栈变量吗?这里的一个更具体的例子:后访问本地变量“删除”

class RefCountedClass 
{ 
public: 
    RefCountedClass(Mutex& m) : 
     mutex_(m) 
    {} 

    . 
    . 
    . 

private: 
    Mutex& mutex_; 

    void RemoveReference() 
    { 
     // As I understand, mutex_ will be destroyed after delete, 
     // but using m is all right because it is on-stack and 
     // references an external object. Am I right? 
     Mutex& m = mutex_; 
     m.Acquire(); 

     --recount_; 
     if (refcount <= 0) delete this; 

     m.Release(); 
    } 
}; 
+0

有对象的引用计数自己是一个坏主意(它可以告诉如果它是一个静态的生命周期(堆栈)或动态生命周期(堆)变量?这就是COM的工作方式,以及我们已经从C++社区获得的经验;从boost :: shared_ptr可以看出,引用计数是而不是参考对象的一部分。 – 2010-08-06 18:10:58

+0

@MartinYork我同意你的观点。在一般情况下,我不会建议自己实施这样的参考计数。尽管如此,这是一个特例。幸运的是,在我的真实情况下,构造函数不是公有的,创建受到工厂对象的保护。 – FireAphis 2010-08-08 12:29:01

回答

7

you may do this只要成员变量本身只是与外部对象的引用。

(请原谅以前的错误的答案,我感到困惑的mutex_变量)。

+0

+1。我忽略了分配给本地变量的内容。我更喜欢你的答案,所以我删除了我的。 – Manfred 2010-08-06 09:52:32

0

一般来说,你不准delete this后调用的唯一的事情是什么,说对this参考。这包括任何非静态类成员或函数。

在你的情况,有一个很好的机会,RemoveReference将无法​​正常工作。这是因为m指向mutex_,删除后不再存在。你最好的选择可能是使mutex_静态。

编辑:虽然mutex_点,它仍然类被删除后,存在一个外部变量,没有防弹保证类被删除后获得的值,编译器不会重提mutex_外部互斥体。事情很可能按预期工作,但我不相信这是可以保证的。

+0

不,'m'不指向'mutex_',而是指向'mutex_'指向的任何地方:注意'mutex_'本身就是一个引用! – 2010-08-06 09:53:48

+0

看我的编辑 - 我假设一个引用被视为一个指针,但作为一个引用,编译器可能会缓存互斥锁的值,并让事情按预期工作。 – doron 2010-08-06 10:20:46

+3

如果编译器做你猜测它可能,它被打破。这是合法的C++。换言之,这种情况与'int a = myIntegerMemberVariable_;删除这个; doSomethingWith(一);'?在这种情况下是不是很清楚,任何编译器将“优化”为'doSomethingWith(this-> myIntegerMemberVariable _);'被破坏? – 2010-08-06 10:45:19

0

是在这种情况下。您的堆栈变量“M”指向您在构造函数中

1

是获取外部资源,你可以,但为什么不使用原子递减而不是互斥下递减计数器?你真的需要保护(通过互斥)对象的破坏吗?的确,在计数器成为0之后,唯一的当前线程可以访问该对象。

所以,也许有可能重写代码

 
    int tmp_count; 
    m.Acquire(); 
     tmp_count= --recount_; 
    m.Release(); 
    if (tmp_count <= 0) delete this; 

(或使用原子能递减和测试计数器)

+1

**危险**!这可能会在您测试'tmp_count <= 0'时进行双删除。相反,测试'== 0'是安全的。但是这个例子很好地说明了为什么并发代码很难正确使用。 – 2010-08-06 11:43:22

+0

如果程序包含另一个bug (recount_不能小于0)会很危险;但通常我同意在这种情况下 ==更可接受。 +1关于并发代码。花费时间来分析和验证这样的代码可能比编写它的时间大10..20..50倍。 – user396672 2010-08-06 12:42:22