管理套接字文件描述符的智能指针

smart pointer to manage socket file descriptor

如果指针超出范围,智能指针会清除内存。我想让它适应文件描述符,比如套接字。您需要一个用户定义的删除器,因为 close() 是释放文件描述符 (fd) 资源的函数。

我发现 this 有用的页面,不幸的是,大多数方法对我都不起作用。下面是我到目前为止找到的一个可行的解决方案,有点讨厌。因为 uniqu_ptr 需要我创建的指针 int *fd 来存储 fd 值,因此,我不得不在我的自定义删除器中关闭(*fd)并删除 fd。

(1)有没有更好的方法?

基于上述网页提供的提示的选项 A 和 B 更好,但会导致奇怪的编译器错误。

(2)有谁知道如何正确使用这些替代品吗?

我正在使用带有 CONFIG += c++11 选项和 gcc 版本 4.8.2 的 Qt Creator 3.0.1

#include "ccommhandler.h"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <memory>

#include <qdebug.h>

//for Option A and B
struct CloseHandleDeleter {
    typedef int pointer;
    void operator()(int handle) const
    {
    }
};

//custom deleter, working
class MyComplexDeleter
{

public:
    MyComplexDeleter() {}

    void operator()(int* ptr) const
    {
        qDebug() << "Deleting ";
        close(*ptr);
        delete ptr;
    }
};

CCommHandler::CCommHandler()
{
    //Option A doesn't work
    //std::unique_ptr<int, CloseHandleDeleter> file( socket(AF_INET, SOCK_STREAM, 0) );
    //Option B doesn't work
    //std::unique_ptr<int, int()(int)> filePtr(  socket(AF_INET, SOCK_STREAM, 0) , close);

    MyComplexDeleter deleter;
    int *fd = new int;
    *fd = socket(AF_INET, SOCK_STREAM, 0);
    std::unique_ptr<int, MyComplexDeleter> p( fd , deleter);

}

编辑:

Nevin 贴出的答案是对的,解决了我最初的问题

learnvst 的评论让我重新考虑了我的问题,我不得不说我可能把它弄得比需要的复杂得多,因为下面的简单 class 应该也能解决我的自动释放内存问题资源或在我的情况下,关闭文件描述符:

class SocketHandler
{
   int _fd;
 public:
   SocketHandler(int FD):_fd(FD){}
   ~SocketHandler() { if(_fd!=-1) close(_fd); }

   operator int() const { return _fd; }
};

因为 fd 不是指针,所以我不会尝试将其归入 unique_ptr。相反,创建一个自定义 class,其界面基于 unique_ptr,如(注意:完全未经测试):

class unique_fd
{
public:
    constexpr unique_fd() noexcept = default;
    explicit unique_fd(int fd) noexcept : fd_(fd) {}
    unique_fd(unique_fd&& u) noexcept : fd_(u.fd_) { u.fd_ = -1; }

    ~unique_fd() { if (-1 != fd_) ::close(fd_); }

    unique_fd& operator=(unique_fd&& u) noexcept { reset(u.release()); return *this; }

    int get() const noexcept { return fd_; }
    operator int() const noexcept { return fd_; }

    int release() noexcept { int fd = fd_; fd_ = -1; return fd; }
    void reset(int fd = -1) noexcept { unique_fd(fd).swap(*this); }
    void swap(unique_fd& u) noexcept { std::swap(fd_, u.fd_); }

    unique_fd(const unique_fd&) = delete;
    unique_fd& operator=(const unique_fd&) = delete;

    // in the global namespace to override ::close(int)
    friend int close(unique_fd& u) noexcept { int closed = ::close(u.fd_); u.fd_ = -1; return closed; }

private:
    int fd_ = -1;
};