将不透明指针包裹在shared_ptr中

Wrap an opaque pointer in a shared_ptr

本文关键字:ptr shared 不透明 指针 包裹      更新时间:2023-10-16

我正在尝试使用 winsock2 实现一个简单的 TCP 服务器应用程序。为此,我有一个接受连接的类(TcpServer(和一个处理连接的类(TcpListener(。为此,这些对象需要共享SOCKET,whis 被定义为UINT_PTR。安全地分享这一点似乎是shared_ptr要走的路。不幸的是,似乎shared_ptr应该包装一个structclass,因此我在下面的实现。

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版本,它提供了实际的套接字参数。 所以你不是read( ClientSocket.Socket, ...)而是写ClientSocket.read(...).
  • 恢复为 SafeSocket 作为 typedef,但将附加函数放在 SafeSocket_ 中,以便编写ClientSocket->read(...)

我想我更喜欢中间的解决方案。