C++ 作用域引用习惯用法的最佳实践?

C++ 作用域引用习惯用法的最佳实践?,c++,pointers,C++,Pointers,我刚刚被一个bug烧坏了,部分原因是我缺乏理解,部分原因是我认为我们的代码库设计不太理想。我很好奇如何改进我的5分钟解决方案 我们正在使用ref计数对象,在这些类的对象上有AddRef()和Release()。一个特定的对象是从ref count对象派生的,但是一个获取这些对象的实例的公共函数(GetExisting)在自身中隐藏了一个AddRef(),而不显示它正在这样做。这就需要在函数块的末尾发布一个版本来释放隐藏的ref,但是没有检查GetExisting()实现的开发人员不会知道这一点,

我刚刚被一个bug烧坏了,部分原因是我缺乏理解,部分原因是我认为我们的代码库设计不太理想。我很好奇如何改进我的5分钟解决方案

我们正在使用ref计数对象,在这些类的对象上有AddRef()和Release()。一个特定的对象是从ref count对象派生的,但是一个获取这些对象的实例的公共函数(GetExisting)在自身中隐藏了一个AddRef(),而不显示它正在这样做。这就需要在函数块的末尾发布一个版本来释放隐藏的ref,但是没有检查GetExisting()实现的开发人员不会知道这一点,而忘记在函数末尾添加一个版本的人(比如,在修复bug的关键时刻)会泄漏对象。当然,这是我的烧伤


void SomeFunction(ProgramStateInfo *P)
{
   ThreadClass *thread = ThreadClass::GetExisting( P );
   // some code goes here
   bool result = UseThreadSomehow(thread);
   // some code goes here
   thread->Release();  // Need to do this because GetExisting() calls AddRef()
}
因此,我编写了一个小类,以避免在这些函数结束时需要Release()


class ThreadContainer
{
private:
    ThreadClass *m_T;
public:
    ThreadContainer(Thread *T){ m_T = T; }
    ~ThreadContainer() { if(m_T) m_T->Release(); }
    ThreadClass * Thread() const { return m_T; }
};
所以现在我可以这样做:


void SomeFunction(ProgramStateInfo *P)
{
   ThreadContainer ThreadC(ThreadClass::GetExisting( P ));
   // some code goes here
   bool result = UseThreadSomehow(ThreadC.Thread());
   // some code goes here
   // Automagic Release() in ThreadC Destructor!!!
}
我不喜欢的是,为了访问线程指针,我必须调用ThreadContainer的成员函数thread()。是否有一些聪明的方法可以让它在语法上更漂亮,或者类似的东西会模糊容器的含义,给不熟悉代码的开发人员带来新的问题

谢谢。

看一看。它允许这样的语法(不知羞耻地从该链接中窃取):

或者你可以试试:


是的,您可以为类实现
operator->()
,该类将递归调用
operator->()
,无论返回什么:

class ThreadContainer
{
private:
    ThreadClass *m_T;
public:
    ThreadContainer(Thread *T){ m_T = T; }
    ~ThreadContainer() { if(m_T) m_T->Release(); }
    ThreadClass * operator -> () const { return m_T; }
};
它有效地为包装器类使用了智能指针语义:

Thread *t =  new Thread();
...
ThreadContainer tc(t);
...
tc->SomeThreadFunction(); // invokes tc->t->SomeThreadFunction() behind the scenes...
您还可以编写一个转换函数,以类似的方式启用
useThreadContainer(ThreadContainer tc)
类型调用

如果Boost是一个选项,我认为您可以设置一个
共享\u ptr
作为智能参考。

使用Boost::共享\u ptr
您可以定义自己的析构函数,如下一个示例中的我们:

您可以添加自动类型转换操作符来返回原始指针。微软的CString类使用这种方法来轻松访问底层的字符缓冲区,我总是觉得它很方便。使用这种方法可能会发现一些令人不快的惊喜,因为在任何时候你都有一个隐式转换,但我没有遇到任何

class ThreadContainer
{
private:
    ThreadClass *m_T;
public:
    ThreadContainer(Thread *T){ m_T = T; }
    ~ThreadContainer() { if(m_T) m_T->Release(); }
    operator ThreadClass *() const { return m_T; }
};

void SomeFunction(ProgramStateInfo *P)
{
   ThreadContainer ThreadC(ThreadClass::GetExisting( P ));
   // some code goes here
   bool result = UseThreadSomehow(ThreadC);
   // some code goes here
   // Automagic Release() in ThreadC Destructor!!!
}

我建议遵循bb并使用boost::shared\u ptr。如果boost不是一个选项,那么您可以看看std::auto_ptr,它很简单,可能满足了您的大多数需求。考虑到std::auto_ptr具有您可能不想模仿的特殊移动语义


该方法提供了*和->运算符,以及一个getter(用于原始指针)和一个release操作,以防您想要释放内部对象的控制。

这在使用中是什么样子的?啊,我明白了。这将调用隐藏成员上的函数(这很有用,谢谢),但我想我想要的是一种更干净的方法,将隐藏成员传递到函数中,可能是将容器类别名为隐藏类。我想我可以过载()并让返回m_T…不,那不行。您将需要从ThreadContainer到Thread*的自动转换,这是可能的,但可能会变得棘手。真的,如果你能使用Boost,我建议你看看下面bb的Boost建议。shared_ptr听起来正是你想要的。Boost的好处是它已经被大量调试,完全符合你想要的替代用途……啊,这是我一直在寻找的,我只是不知道怎么做。Mark Ransom的答案就是我想要的,但是你的回答让我在学习新东西和更高层次的整体问题解决方案方面有了一个很好的方向,所以我将它标记为“答案”。谢谢,很高兴听到。不客气。对于所有类似的事情,最好使用一个genreic类,而不是为每个类编写单独的解决方案。
Thread *t =  new Thread();
...
ThreadContainer tc(t);
...
tc->SomeThreadFunction(); // invokes tc->t->SomeThreadFunction() behind the scenes...
class ThreadContainer
{
private:
    ThreadClass *m_T;
public:
    ThreadContainer(Thread *T){ m_T = T; }
    ~ThreadContainer() { if(m_T) m_T->Release(); }
    operator ThreadClass *() const { return m_T; }
};

void SomeFunction(ProgramStateInfo *P)
{
   ThreadContainer ThreadC(ThreadClass::GetExisting( P ));
   // some code goes here
   bool result = UseThreadSomehow(ThreadC);
   // some code goes here
   // Automagic Release() in ThreadC Destructor!!!
}