将不透明指针包装在shared_ptr中
问题描述:
我试图使用winsock2实现简单的TCP服务器应用程序。为此,我有一个接受连接的类(TcpServer
)和一个处理连接的类(TcpListener
)。为此目的,这些物体需要共享SOCKET
,whis被定义为UINT_PTR
。为了安全地分享这个shared_ptr
似乎是要走的路。不幸的是,shared_ptr
似乎应该包装struct
或class
,因此我的实施如下。将不透明指针包装在shared_ptr中
struct SafeSocket_
{
SOCKET Socket;
SafeSocket_(SOCKET socket)
: Socket(socket)
{}
~SafeSocket_()
{
closesocket(Socket);
std::cout << "destroyed SafeSocket_" << std::endl;
}
};
typedef std::shared_ptr<SafeSocket_> SafeSocket;
要创建/接受一个新的套接字我使用以下可怕的代码。更糟的是,我需要在各地使用ClientSocket->Socket
。
SafeSocket ClientSocket = SafeSocket(new SafeSocket_(accept(ListenSocket, NULL, NULL)));
必须有处理这个除了使用一个漂亮的包装库一个更好的办法。
注意:我知道有一些不错的包装库,比如来自boost的asio,但我只是为了让我的头脑解决一些C++基础问题而烦恼。
答
基本问题是UINT_PTR
不是一个不透明的指针。这是一个整数。如果它是typedef struct __socket SOCKET;
,那么你可以只写std::shared_ptr<decltype(*SOCKET{})>
,在自定义删除程序中调用close_socket,你会笑。
有许多可能的方法:
- 制作
SafeSocket
是包含shared_ptr的一类,并且具有socket
成员函数。然后你在那里写ClientSocket.socket()
。 - 如上所述,但给出
SafeSocket
版本的套接字函数,并且它提供了实际的套接字参数。因此,您可以编写ClientSocket.read(...)
而不是read(ClientSocket.Socket, ...)
。 - 恢复到
SafeSocket
作为一个typedef,而是把更多的功能SafeSocket_
,所以你写ClientSocket->read(...)
我想我更喜欢中间的最佳解决方案。
好主!我们进行了三次编辑,让它几乎正确! –
使用自定义[在std :: unique_ptr中有'SOCKET']是可能的(http://stackoverflow.com/questions/24611215/one-liner-for-raii-on-non-pointer) 'Deleter'将'SOCKET'定义为'pointer'类型,即使它不是一个真正的指针。不知道是否可以用'std :: shared_ptr'完成同样的工作,尽管它也支持自定义的'Deleter',但也许或者不是自定义指针?我还没有挖掘到它看。 –
我选择了中间解决方案。 Remy表示会很好,但我现在意识到将资源编号包装在指针容器中会造成混淆。 – Wouter