【问题标题】:Idiomatic move contructor for resource that can only be released once in destructor只能在析构函数中释放一次的资源的惯用移动构造函数
【发布时间】:2016-07-04 22:56:16
【问题描述】:

在包装资源的代码中,该资源应该被释放一次且只释放一次,执行以下类似的操作来保证这一点是惯用的吗?有没有更好的方法?

class SocketWrapper { 
    SocketWrapper() {
        fd = socket(AF_INET, SOCK_STREAM, 0);
    }

    ~SocketWrapper() {
        if(fd < 0){
            close(fd);
        }
    }

    SocketWrapper(SocketWrapper &&other){
        fd = other.fd;
        other.fd = -1;
    }
    //similar move assignment   

private: 
    int fd{-1};
};

【问题讨论】:

  • 你应该使用 -1 因为 0 是一个有效的 FD。
  • 谢谢,我会编辑的。
  • 是的,这是惯用的。不,我不知道有什么更好的方法。请注意,我同意@ysdx,但我会说使用为目标平台指定的任何无效值(INVALID_SOCKET-1 等)。
  • 那么您应该更改 dtor 中的检查,因为任何非零 int 的计算结果都是 true。也就是说,在这种成员复杂度较低的情况下,我会根据移动赋值运算符定义移动 ctor - 你保证它们在这种情况下匹配。
  • 我想你会想要修复你的析构函数,因为你已经更新了 fd 的初始值。

标签: c++ c++11 move-semantics raii


【解决方案1】:

为了安全起见,您也应该删除该类的复制构造函数。

SocketWrapper(const SocketWrapper&) = delete;

这应该是安全的,但我想如果你希望资源也被创建一次,你可以使用单例。有些库提供开箱即用的单例功能。例如:-Folly singleton

此外,始终建议重用库,这些库在原始套接字上提供退出包装器,并且经过广泛测试,因此使用起来很健壮,而不是重写整个包装愚蠢的AsyncSocket,它提供了类似的抽象,除非你只想要基本的 fd 包装功能。

【讨论】:

  • 一旦声明了移动构造函数,复制构造函数就会被隐式删除。显式删除它并没有什么坏处,但没有必要。
  • 我认为定义移动 ctor/assignment 运算符会隐式删除复制 ctor/assignment?
【解决方案2】:

我想推荐您使用与智能指针类似的策略。 shared_ptr 和 unique_ptr 都用于管理指针资源。

对于不同数量的所有者,您可以选择一个。参考:Differences between unique_ptr and shared_ptr

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-21
    • 2015-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-01
    • 2011-05-22
    相关资源
    最近更新 更多