管理套接字文件描述符的智能指针
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;
};
如果指针超出范围,智能指针会清除内存。我想让它适应文件描述符,比如套接字。您需要一个用户定义的删除器,因为 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;
};