一旦引用计数达到 0,就让shared_ptr 调用成员函数
我正在为不能与 DuplicateHandle 一起使用的 HANDLE 创建一个包装器,因此我尝试将句柄包装在共享指针中。
想象一下以下代码:
class CWrapper
{
public:
CWrapper() :
m_pHandle(new HANDLE, &CWrapper::Close)
{
//code to open handle
}
private:
void Close()
{
//code to close handle
}
std::shared_ptr<HANDLE> m_pHandle;
}
我还尝试使用 HANDLE 参数创建 close (不理想)。无论哪种方式,我都会收到编译器错误“Term 不会计算为采用 0 个参数的函数”。这是因为隐式的 this 指针吗?我该如何解决这个问题?如何从共享指针调用成员函数?
I'm creating a wrapper for a HANDLE that does not work with DuplicateHandle, so instead I am trying to wrap the handle in a shared_ptr.
Imagine the following code:
class CWrapper
{
public:
CWrapper() :
m_pHandle(new HANDLE, &CWrapper::Close)
{
//code to open handle
}
private:
void Close()
{
//code to close handle
}
std::shared_ptr<HANDLE> m_pHandle;
}
I have also tried creating close with a HANDLE parameter (not ideal). Either way, I get the compiler error "Term does not evaluate to a function taking 0 arguments". Is this because of the implicit this pointer? How do I fix this? How do I call a member function from the shared pointer?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在 boost::shared_ptr 文档中查找
deleter
。我找不到它的直接链接,但基本上它是一个函子,当 ref 为 0 时被调用。Look for
deleter
in boost::shared_ptr docs. I couldn't find a direct link to it, but basically it is a functor that is called when the ref is 0.我还没有测试过,但是根据 shoosh 提出的想法,您也许可以传递这样的成员函数:
I haven't tested it, but based on the idea presented by shoosh, you may be able to pass a member function like this:
如果您需要从
Close
中访问非静态成员,则需要正确绑定其this
参数,但这包含一个隐藏的错误。您的对象是可复制的,并且您将删除器绑定到
*this
的对象。该句柄与您创建的第一个包装器相关联,但如果您复制该包装器,该句柄将被共享,但与第一个包装器相关联,该第一个包装器可能不再存在:执行该代码后,
x
将被销毁,行为未定义,因为x
内部句柄指针的销毁将尝试使用w
构造函数调用中绑定的对象 - 然而该对象并不不存在了!解决这个问题的方法是将与句柄关联的数据存储在分配的对象本身中,而不是尝试将其存储在顶级句柄对象中,如下面的代码所示。
辅助数据不再存储在句柄中,而是以及包装器的所有副本之间共享的数据。共享数据本身是使用其正常的构造函数和析构函数创建和销毁的。
最后一个退出的包装器将销毁句柄,该句柄在所有包装器之间显式共享。
If you need to access non-static members from within
Close
you need to bind itsthis
argument properlyThis, however contains a hidden bug. Your object is copyable, and you bind the deleter to the object of
*this
. The handle is associated with the first wrapper you create, but if you copy the wrapper, the handle is shared but associated with the first wrapper, which may not exist anymore:After that code was executed and
x
is going to be destroyed, behavior is undefined becausex
's destruction of the internal handle pointer will try to use the object bound inw
's constructor invokation - however that object doesn't exist anymore!A solution to this can be to store the data associated with the handle in the allocated object itself, instead of trying to store it in the toplevel handle object, like in the following code
The auxilary data is not not stored in the handle anymore, but together with the data that's shared among all copy of the wrapper. The shared data itself is created and destroyed using its normal constructor and destructor.
The last wrapper going out of life will destroy the handle, which is explicitly shared among all wrappers.
我认为你的抽象方式是错误的。
shared_ptr
为您提供了一个可复制的共享资源“句柄”,但该共享资源本身无法复制。将shared_ptr
与删除时不执行自身清理的类型一起使用并不是最佳用途。如果让你的类有单一责任在其析构函数中正确清理这个固有的不可复制资源,那么你可以使用
shared_ptr
来提供共享所有权,这就是它的单一责任。 (我认为HANDLE
是不可复制的,就像您尝试制作HANDLE
的简单副本一样,副本不能被视为独立;最后一个副本必须正确关闭因此副本的所有者需要了解存在的其他副本。)现在在需要共享句柄的地方使用
shared_ptr
,如果您认为这太冗长,可以使用 typedef 。恕我直言,自定义删除器是一个过于复杂的解决方案。
I think you have your abstractions the wrong way around.
shared_ptr
gives you a copyable "handle" to a shared resource that can't itself be copied. Usingshared_ptr
with a type that doesn't perform its own cleanup when it is deleted isn't an optimal use.If make your class' single responsibility to clean up this inherently non-copyable resource properly in its destructor, then you can use
shared_ptr
to provide shared ownership which is what its single responsibility should be. (I considerHANDLE
to be non-copyable as if you try to make a simple copy of aHANDLE
the copies cannot be treated as independent; the last copy must be correctly closed so the owners of copies would need to know about other copies in existence.)Now use
shared_ptr<CWrapper>
where you need to shared the handle, you can use a typedef if you think that this is too verbose.A custom deleter is an overly complex solution, IMHO.
您不能调用成员函数,但可以使用作为全局函数的自定义删除器,如下所示:
You can't call a member function but you can use a custom deleter that is a global function like so: