【问题标题】:Passing shared_ptr to std::function (member function)将 shared_ptr 传递给 std::function (成员函数)
【发布时间】:2015-11-06 08:58:53
【问题描述】:

以下观察者类在其 ctor 执行时通过调用 attach 向主题注册一个回调函数。我希望观察者的 dtor 取消注册回调函数。

如何将相同的指针传递给detach,就像传递给attach 一样,以便主体可以将其从观察者列表中删除?

我想我必须将shared_ptr 存储到this,但我不确定如何从shared_ptr 到成员函数callback。

谁能帮忙?

Observer::Observer(Subject& subject) : m_subject(subject),
{
    m_subject.attach("cmd", std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this)));
}

Observer::~Observer()
{
    // I tried this initially but realised that the pointer below
    // is different to the one passed to `attach` from the ctor.

    m_subject.detach("cmd", std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this)));
}

void Observer::callback()
{
    // do some stuff
}

attach 和 detach 声明如下:

void Subject::attach(const std::string& command, const std::shared_ptr<std::function<void()>>& callback);

void Subject::detach(const std::string& command, const std::shared_ptr<std::function<void()>>& callback);

【问题讨论】:

  • 有什么特殊原因导致您不在 ctor 参数列表中使用 const Subject&amp; 吗?我问是因为你显然是在复制一个副本。
  • @Superlokkus 因为Subject::attach 不是const。
  • 所以m_subject 也是Subject &amp;?否则,您正在创建主题的副本,然后它就无关紧要了。
  • 是的,m_subject 是 Subject&amp;。
  • 只是想确保你得到你想要的:-)。请不要忘记用接受标记答案;-))

标签: c++ c++11 shared-ptr std-function


【解决方案1】:

我建议也将shared_ptr 的副本存储在您的观察者类中,也许作为成员。然后你可以给detach提供相同的指针。

像这样:

class Observer {
    //Other Stuff here

private:
    std::shared_ptr<std::function<void()>> callback_ptr;
};

Observer::Observer(Subject& subject) : 
m_subject(subject), 
callback_ptr(std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this))
{
    m_subject.attach("cmd", std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this)));
}

Observer::~Observer()
{
    m_subject.detach("cmd", callback_ptr));
}

值得注意的是,正如@dkg 也提到的,make_shared 每次调用时总是返回一个新的shared_ptr,因为它的目的是“创建一个具有以下参数的新对象并返回一个@987654326 @给它”。大致相当于shared_ptr(new std::function&lt;void()&gt; (std::bind(&amp;Observer::callback, this))。 有一个额外的make_shared 函数的原因是为了最小化分配并保证长表达式中的异常安全。 如果您只想共享一个对象,那么只需分发您的shared_ptr 的副本。

【讨论】:

  • 这就是解决方案。否则,使用make_shared 在 dtor 中创建一个新实例,并且传递的共享指针指向这个新实例,而不是在 ctor 中创建的那个...
【解决方案2】:

您每次调用std::make_shared 时,它都会为您分配并构造一个新对象。

在您的代码中,您调用它两次,然后您的对象有两个不同的实例。

您可以调用它一次并将共享指针保留为您的类的成员。

【讨论】:

    猜你喜欢
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 1970-01-01
    • 1970-01-01
    • 2017-03-22
    • 1970-01-01
    相关资源
    最近更新 更多