【发布时间】:2015-04-13 20:46:16
【问题描述】:
如果指针超出范围,智能指针会清除内存。我想把它适应一个文件描述符,比如一个套接字。你需要一个用户定义的删除器,因为 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 SocketHandler
{
int _fd;
public:
SocketHandler(int FD):_fd(FD){}
~SocketHandler() { if(_fd!=-1) close(_fd); }
operator int() const { return _fd; }
};
【问题讨论】:
-
为什么不把套接字的东西包装到一个类中并关闭 dtor 中的套接字呢?然后你不需要使用删除器,因为当智能指针释放资源时,一切都会很好地结束。
-
一个
unique_ptr必须持有一个指针。socket()在非 Windows 平台上不返回 指针。这就是为什么选项 A 和 B 不起作用,但选项 C 起作用的原因。
标签: sockets c++11 smart-pointers