【问题标题】:c++ std::bind keeping object alivec++ std::bind 保持对象存活
【发布时间】:2012-10-20 10:54:18
【问题描述】:

这是代码,非常简单。

class Foo
{
public:
    void print()
    {
        std::cout<<"Foo::print\n";
    }
}; 


Game::Game()
{
    {
        Foo foo;
        player.onclick = bind(&Foo::print,foo);

    }
    player.onclick();
}

内部作用域完成后 foo 对象超出作用域,但 print 方法仍然被调用,我猜这是因为 player 持有对 foo 对象的引用?有没有办法阻止这种情况发生?我不希望对象在应该被销毁时保持活动状态并接收事件。

谢谢。

【问题讨论】:

  • 该代码并不简单。剩下的在哪里?
  • 您还需要什么? bind 是 std::tr1::bind。 onclick 是一个像这样的简单函数 std::function onclick;也删除了不必要的播放器内容。
  • 所以你使用 tr1::bind。在这种情况下,我需要包括、主要等

标签: c++ c++11


【解决方案1】:

您正在绑定到foo 的副本;该副本的持续时间与绑定的函数对象一样长,而原始的 foo 在其作用域结束时被销毁。

如果你不想让它活着,那么绑定到一个指针(&amp;foo)或者一个引用(std::ref(foo));然后你必须小心,一旦foo 超出范围,就不要调用函数对象。请注意,无法从函数对象中看出这已经发生了;调用它会给出未定义的行为。

为了在对象被销毁时安全地断开它,您必须安排其析构函数重新分配onclick,或者让其他对象负责首先重新分配onclick,然后销毁该对象。

【讨论】:

  • 好的,所以我将绑定更改为:Foo foo; player.onclick = bind(&Foo::print,&foo);而且 print 方法仍在被调用,这不是我所期望的。
  • @BlackKnight:是的,函数对象仍然可以调用,但是在 foo 被销毁后调用它会产生未定义的行为(在这种情况下,该行为可能会打印消息,因为成员函数不对死对象做任何事情)。如果您需要安全地使函数对象失效,那么您需要以某种方式自己执行此操作。
  • 我能看到的唯一方法是创建一个 Foo 析构函数并设置一个僵尸标志,然后如果对象已死,则立即从处理程序返回。有没有办法打破 player.onclick 和 Foo.print 之间的绑定?
  • @BlackKnight :如果对象被摧毁,检查僵尸标志将无济于事——你还在 UB 领域。
  • @BlackKnight,您实际上可以创建某种智能指针,它将包裹在实际的 Foo 类中,并且在 Foo 的析构函数中,您可以对这个容器说设置“僵尸标志”
【解决方案2】:

从您的描述看来,您实际上想要一个事件循环。虽然std::bind 对于类似的事情很有用,但它本身并不是一个整体。我建议你看看boost.signals

【讨论】:

    【解决方案3】:

    我认为当您将Foo 分配给Player 时,您应该使用shared_ptr,并在Player 中保留weak_ptrFoo。然后尝试锁定onclick函数中的weak_ptr,看看Foo是否还活着。像这样的:

    using namespace std;
    class Foo
    {
        public:
            void print()
            {
                cout<<"Foo::print\n";
            }
    }; 
    
    class Player
    {
        public:
            weak_ptr<function<void()>> _onClickFuntion;
            void onclick()
            {
                shared_ptr<function<void()>> tempFunction(_onClickFunction.lock());
                if (tempFunction)
                    tempFunction();
            }
    }
    
    Game::Game()
    {
        {
            Foo foo;
            player._onClickFuntion = shared_ptr<function<void()>>(new bind(&Foo::print,foo));
        }
        player.onclick();
    }
    

    【讨论】:

      猜你喜欢
      • 2014-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-27
      • 2011-06-19
      • 2012-05-20
      • 1970-01-01
      相关资源
      最近更新 更多