使用unique_ptr来控制文件描述符

Sha*_*esh 7 c++ smart-pointers unique-ptr c++11 gcc4.7

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

#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
Run Code Online (Sandbox Code Playgroud)

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

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!='
Run Code Online (Sandbox Code Playgroud)

从钻研到定义unique_ptr,我可以看到两个阻碍它工作的问题.第一个似乎明显违反标准的是析构函数,用于unique_ptr比较"指针"(根据我的定义,是一个int),nullptr以查看它是否已初始化.这与通过布尔转换报告它的方式形成对比,布尔转换是将其与"pointer()"(未初始化的"指针")进行比较.这是我看到的错误的原因 - 整数不能与a相比nullptr.

第二个问题是我需要一些方法来告诉unique_ptr未初始化的值是什么.我希望以下代码段能够正常工作:

unique_fd fd( open(something...) );

if( !fd )
    throw errno_exception("Open failed");
Run Code Online (Sandbox Code Playgroud)

要使其工作,unique_ptr需要知道"未初始化的值"为-1,因为零是有效的文件描述符.

这是一个错误gcc,还是我试图在这里做一些根本无法做到的事情?

Nic*_*las 9

由露出的类型Deleter::pointer必须满足NullablePointer要求.其中最重要的是,这种表达必须是合法的:Deleter::pointer p = nullptr;.当然,nullptr几乎可以通过它不能隐式转换为数字这一事实来定义,因此这不起作用.

你必须使用一个可以隐式构造的类型std::nullptr_t.像这样的东西:

struct file_desc
{
  file_desc(int fd) : _desc(fd) {}
  file_desc(std::nullptr_t) : _desc(-1) {}

  operator int() {return _desc;}

  bool operator ==(const file_desc &other) const {return _desc == other._desc;}
  bool operator !=(const file_desc &other) const {return _desc != other._desc;}
  bool operator ==(std::nullptr_t) const {return _desc == -1;}
  bool operator !=(std::nullptr_t) const {return _desc != -1;}

  int _desc;
};
Run Code Online (Sandbox Code Playgroud)

您可以将其用作Deleter::pointer类型.

  • 你应该使用`-1`来表示`nullptr`.`0`是有效的fd(虽然很少关闭). (5认同)

Yon*_* Wu 6

你可以做一些简单的事情,如下所示吗?

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;
};
Run Code Online (Sandbox Code Playgroud)

我不明白为什么你必须使用unique_ptr,它旨在管理指针.