【问题标题】:RAII with std::function带有 std::function 的 RAII
【发布时间】:2020-08-19 08:38:56
【问题描述】:

std::function 本质上是否像 std::shared_ptrstd::unique_ptr 一样聪明?我觉得不是?我有一个std::function,它是一个类成员,如下所示。

class MyClass {
    typedef std::function<void(void)> Func;
    Func m_func;

public:
    MyClass() {
        m_func = []() {
            std::cout << "Func called" << std::endl;
        }
    }

    ~MyClass() {
       m_func = nullptr; // Is this required? 
    }
}

问题:
是否必须在析构函数中将nullptr 分配给m_func?或者我应该通过执行以下操作将m_func 变成智能指针?还是m_func默认聪明,隐含跟随RAII?

class MyClass {
    typedef std::function<void(void)> Func;
    std::unique_ptr<Func> m_func;

public:
    MyClass() {
        m_func = std::make_unique<Func>();
        *m_func = []() {
            std::cout << "Func called" << std::endl;
        }
    }

    ~MyClass() {
       // auto released
    }
}

【问题讨论】:

  • std::function 非常非常聪明。按照您发布到析构函数部分的链接。
  • 好的。听起来我不需要将它包装在唯一或共享指针中。
  • 有点奇怪,在en.cppreference.com/w/cpp/utility/functional/function的官方文档中没有提到它是聪明的。官方文档宁愿在注释中提到这样的事情,这有点令人困惑并且听起来不是 RAII - “当从没有尾随返回类型的 lambda 表达式初始化结果类型为引用的 std::function 时应小心。”
  • 该注释与您的问题没有太大关系。请参阅std::function::~function 以获取您问题的直接答案:销毁 std::function 实例。如果 std::function 不为空,它的目标也被销毁。
  • 我很确定所有 std 类都遵守 3/5/0 规则,即使可加入的 std::thread 可能被认为是特殊的;-)

标签: c++ c++11 smart-pointers std-function raii


【解决方案1】:

std::function 有一个析构函数,可以删除它管理的所有资源(如果有的话)。这一行:

   m_func = nullptr; // Is this required? 

从来不需要。自动调用类成员析构函数,如果没有,分配nullptr 永远不是“正确”的事情。如果m_func 是一个指针,您将失去指针值以及删除它指向的内容的能力。

有点奇怪,官方文档中没有提到它是聪明的......

cppreferencestd::functions 析构函数:

销毁 std::function 实例。如果 std::function 不为空,它的目标也被销毁。

一般来说,可以安全地假设一个类清理了它在其析构函数中管理的任何资源,否则它可以被认为是损坏的。在析构函数中清理资源并不是智能指针带来的新事物。智能指针仅适用于 C++ 中存在的 RAII,始终指向封装动态分配内存管理的指针。

【讨论】:

  • 可以nullptr 分配给std::function 对象,这具有清除它的效果(它是API 的一部分)。不过,您关于不需要在析构函数中执行此操作的观点仍然有效。
  • @Nevin 谢谢。我不得不承认我写这篇文章很匆忙,并不确定nullptr 认为,我只是删除了那句话
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-13
相关资源
最近更新 更多