【问题标题】:Storing member function in a vector and ensuring object still exists when invoked later将成员函数存储在向量中并确保稍后调用时对象仍然存在
【发布时间】:2015-11-05 20:08:04
【问题描述】:

我有一个类X,我想将一个成员函数bar 传递给另一个类Y,它会将它存储在一个向量中并在其他时间调用它。

我知道当Y 调用该函数时,我需要确保X 仍然存在。我该怎么做?

在下面的示例中,我最初认为,如果我将 shared_ptr 传递给 bar,这将满足我的要求 - 即只要存在 Y,那么 X 也会存在, 因为Y 为其成员函数之一持有一个 shared_ptr。

我现在很确定这个逻辑是不正确的。有人可以请教我吗?

class Y {
  std::vector<std::shared_ptr<std::function<void()>>> m_v;
public:
  void foo(const std::shared_ptr<std::function<void()>>& callback) {
    m_v.push_back(callback);
  }

  void sometime_later() {
    // invoke call back function in vector
    // how do I ensure the object I want to call the function on still exists
  }
};

class X {
  Y& m_y;
public:
  X(Y& y) : m_y(y) {
    m_y.foo(std::make_shared<std::function<void()>>(std::bind(&X::bar, this)));
  }

  void bar() {
    // do some stuff
  }
};

【问题讨论】:

  • 您能不能使用比 foo 、 bar、 X 和 Y 更具表现力的名称来使代码更具可读性和想法更易于理解?
  • 你是对的,将shared_ptr 持有到std::function 绑定了X 的成员函数对X 实例的生命周期完全没有影响。如果没有您最终要尝试做的事情的背景,推荐解决方案有点困难。
  • 我不认为std::shared_ptr 的向量会做你想做的事。您正在共享 std::function 而不是 X 的实例。您应该考虑std::shared_ptr 自己被删除时会删除什么。
  • @A.S.H 我认为这个想法是可以理解的。问题很明确。

标签: c++ c++11 callback std-function object-lifetime


【解决方案1】:

这是一个使用std::enable_shared_from_this 结合shared_ptr 的别名构造函数的实现:

#include <vector>
#include <iostream>
#include <memory>
#include <functional>

class Y {
    std::vector<std::shared_ptr<std::function<void()>>> m_v;
public:
    void foo(const std::shared_ptr<std::function<void()>>& callback) {
      m_v.push_back(callback);
    }

    void sometime_later(){
        for (const auto& f: m_v) {
            (*f)();
        }
    }
};

class X : public std::enable_shared_from_this<X> {
  Y& m_y;
  std::function<void()> m_callback;
public:
  X(Y& y) : m_y(y), m_callback(std::bind(&X::bar, this)) {
  }

  void add()
  {
    m_y.foo(std::shared_ptr<std::function<void()>>{shared_from_this(), &m_callback});
    std::cout << shared_from_this().use_count() << "\n";
  }

  void bar() {
      std::cout << shared_from_this().use_count();
  }
};
int main(){

    Y y;
    {
        auto x = std::make_shared<X>(y);
        x->add();
    }
    y.sometime_later();
}

LIVE

【讨论】:

  • 现在要运行,但如果您稍后需要,我会添加更多详细信息
【解决方案2】:

我最终改变了设计以解决我一生的问题。

而不是像下面这样声明一个向量:

std::vector<std::shared_ptr<std::function<void()>>> 

稍后某个时间对存储的函数发出调用,我将其声明为:

std::vector<std::shared_ptr<X>> 

然后要求对象 X 实现一个命名函数(在我上面的示例中,它应该是 bar),然后在适当的时候调用它。这样我可以确保调用回调函数时 X 存在。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-12
    • 2016-03-04
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 2020-11-15
    • 2018-11-03
    • 2012-03-10
    相关资源
    最近更新 更多