如果指针超出范围,智能指针会清除内存。我想将其改编为文件描述符,如套接字。在那里你需要一个用户定义的删除器,因为close()是释放文件描述符(fd)资源的函数。
我发现了this有用的页面,不幸的是,大多数方法对我都不起作用。下面是我发现的一个工作解决方案,这有点令人讨厌。因为uniqu_ptr需要一个我创建int * fd的指针来存储fd值,所以我必须关闭(* fd)并删除自定义删除器中的fd。
(1)有更好的方法吗?
选项A和B基于上述网页提供的提示,但更好,但会导致奇怪的编译错误。
(2)有谁知道如何正确使用这些替代品?
我使用Qt Creator 3.0.1和CONFIG + = c ++ 11选项和gcc版本4.8.2
#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; }
};
答案 0 :(得分:1)
因为fd不是指针,我不会尝试将其归入unique_ptr
。相反,创建一个自定义类,其接口基于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;
};