首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用unique_ptr控制文件描述符

使用unique_ptr控制文件描述符
EN

Stack Overflow用户
提问于 2013-04-02 13:43:02
回答 7查看 7.7K关注 0票数 11

理论上,我应该能够使用自定义指针类型和删除器,以便让unique_ptr管理一个不是指针的对象。我尝试了以下代码:

代码语言:javascript
复制
#ifndef UNIQUE_FD_H
#define UNIQUE_FD_H

#include <memory>
#include <unistd.h>

struct unique_fd_deleter {
    typedef int pointer; // Internal type is a pointer

    void operator()( int fd )
    {
        close(fd);
    }
};

typedef std::unique_ptr<int, unique_fd_deleter> unique_fd;

#endif // UNIQUE_FD_H

这不起作用(带有-std=c++11参数的gcc 4.7 )。它会响应以下错误:

代码语言:javascript
复制
In file included from /usr/include/c++/4.7/memory:86:0,
                 from test.cc:6:
/usr/include/c++/4.7/bits/unique_ptr.h: In instantiation of 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = int; _Dp = unique_fd_deleter]':
test.cc:22:55:   required from here
/usr/include/c++/4.7/bits/unique_ptr.h:172:2: error: invalid operands of types 'int' and 'std::nullptr_t' to binary 'operator!='

通过深入研究unique_ptr的定义,我可以看到两个阻碍它工作的问题。第一个似乎明显违反了标准,那就是unique_ptr的析构函数将“指针”(根据我的定义,这是一个整型)与nullptr进行比较,以查看它是否已初始化。这与它通过布尔转换报告它的方式相反,布尔转换是将它与"pointer()" (一个未初始化的“指针”)进行比较。这就是我看到的错误的原因-整数不能与nullptr相比。

第二个问题是,我需要一些方法来告诉unique_ptr什么是未初始化的值。我想让下面的代码片段正常工作:

代码语言:javascript
复制
unique_fd fd( open(something...) );

if( !fd )
    throw errno_exception("Open failed");

为此,unique_ptr需要知道“未初始化值”是-1,因为零是有效的文件描述符。

这是gcc中的一个bug,还是我试图在这里做一些根本做不到的事情?

EN

回答 7

Stack Overflow用户

发布于 2013-04-02 19:14:10

你能像下面这样做一些简单的事情吗?

代码语言:javascript
复制
class unique_fd {
public:
    unique_fd(int fd) : fd_(fd) {}
    unique_fd(unique_fd&& uf) { fd_ = uf.fd_; uf.fd_ = -1; }
    ~unique_fd() { if (fd_ != -1) close(fd_); }

    explicit operator bool() const { return fd_ != -1; }

private:
    int fd_;

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

我不明白为什么一定要使用unique_ptr,它是用来管理指针的。

票数 10
EN

Stack Overflow用户

发布于 2018-02-02 11:44:07

完整的示例:

代码语言:javascript
复制
#include <memory>
#include <unistd.h>
#include <fcntl.h>

template<class T, T nullvalue, class D, D d> // auto d works in new compilers.
struct generic_delete
{
    class pointer
    {
        T t;
    public:
        pointer(T t) : t(t) {}
        pointer(std::nullptr_t = nullptr) : t(nullvalue) { }
        explicit operator bool() { return t != nullvalue; }
        friend bool operator ==(pointer lhs, pointer rhs) { return lhs.t == rhs.t; }
        friend bool operator !=(pointer lhs, pointer rhs) { return lhs.t != rhs.t; }
        operator T() { return t; }
    };
    void operator()(pointer p)
    {
        d(p);
    }
};
using unique_fd = std::unique_ptr<void, generic_delete<int, -1, decltype(&close), &close>>;
static_assert(sizeof(unique_fd) == sizeof(int), "bloated unique_fd");

int main()
{
    unique_fd fd1(open("fd.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR));
    write(fd1.get(), "hello\n", 6);
}
票数 2
EN

Stack Overflow用户

发布于 2018-12-07 05:22:30

开源Android Framework定义了一个可能满足您需求的unique_fd类:https://android.googlesource.com/platform/system/core/+/c0e6e40/base/include/android-base/unique_fd.h

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15756960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档