【问题标题】:smart pointers in multi-threaded envrionment多线程环境中的智能指针
【发布时间】:2013-07-31 09:35:49
【问题描述】:

我是智能指针的新手。不过,我对它有一个基本的了解。我观察到的是,智能指针必须以与其创建相反的顺序被销毁,否则智能指针可能会出现异常。考虑以下情况:

sharedPtr<abc> my_ptr(new abc); //smart pointer created. Instance counter = 1.
func1(my_ptr);                  //copy constructor in smart pointer called. Instance    counter=2
func2(my_ptr);                  //copy constructor in smart pointer called. Instance counter=3
func3(my_ptr);                  //copy constructor in smart pointer called. Instance counter=4

现在,func3() 不是必须先退出,然后是 func2()func1(),最后是 my_ptr。

问题:如果my_ptr 首先超出范围(并因此尝试删除abc),func1()func2()func3() 仍然指的是@987654330,该怎么办? @(通过智能指针)?

【问题讨论】:

    标签: c++ multithreading smart-pointers reference-counting


    【解决方案1】:

    其实你观察到的是错的。

    智能指针的意义在于解除销毁对象的责任。这意味着当引用计数达到 0 时对象将被删除:先销毁哪个指针并不重要

    在您的情况下,这将是my_ptr 超出范围(假设您没有在您的func() 中制作和保留副本。

    引用计数器应该是这样的:

    {
    sharedPtr<abc> my_ptr(new abc); //smart pointer created. Ref counter = 1.
    func1(my_ptr);                  // Ref counter=2 while in func1
    // Ref count is 1 again.
    func2(my_ptr);                  // Ref counter=2 while in func2
    // Ref count is 1 again.
    func3(my_ptr);                  // Ref counter=2 while in func3
    // Ref count is 1 again.
    } // my_ptr goes out of scope, ref count reach 0, and abc is deleted.
    

    【讨论】:

    • 我明白你的意思。但是,这是我的问题:我想在堆上创建一个事件对象并将这个事件(通过指针传递)传递给观察者类,观察者类又将事件存储在它们各自的 vector 中,以便以后处理它。问题:如何确保所有观察者在有人尝试删除事件之前都已处理该事件?谁应该删除在堆上创建的事件?我不想在 vecotr 中复制事件,而是只想在 vecotr 中存储指向事件的指针。
    • 不要使用vector&lt;event *&gt;,而是使用vector&lt;shared_ptr&lt;event&gt;&gt;。每个观察者都会保留shared_ptr,只要它需要(我想直到事件被处理),并且当它不再需要对事件的引用时会将其从向量中删除。该事件将在最后一个观察者释放指针时自动删除(即,从其向量中删除它)。
    • 这正是我想要使用的。但是,我使用的是自定义 shared_ptr 类而不是标准库类。 (我这样做,只是为了理解这个概念)。这是问题所在: void publishEvent() { sharedPtr start_ev(new start); //创建一个事件-在堆上开始。 start_ev - 参考计数器 = 1 notifyObservers(start_ev); //所有观察者将事件保存在vector> }//oops!!! start_ev 删除事件 start .. 这与错误实现的自定义 sharedPtr 有关吗?
    • 据我所知,是的,这很可能是由于您的sharedPtr 实现中的错误。我建议先玩std::shared_ptr,确保你了解如何使用它们。然后,只有到那时,我认为您应该尝试实现自己的,以了解它们如何在内部工作
    【解决方案2】:

    我不知道您的自定义 sharedPtr,但对于标准 std::shared_ptr,它的工作方式类似于(来自链接参考):

    当发生以下任一情况时,对象将被销毁并释放其内存:

    • 最后一个拥有该对象的 shared_ptr 被销毁。

    • 通过 operator=() 或 reset() 为最后一个拥有该对象的 shared_ptr 分配另一个指针。

    所以对于std::shared_ptr,您可以传递它或制作任意数量的副本,这些副本的销毁顺序无关紧要。

    【讨论】:

      【解决方案3】:

      我观察到的是,智能指针有必要以与其创建相反的顺序被销毁

      嗯,共享智能指针存在的唯一原因是人们不应该关心它们何时被销毁。当最后一个共享指针被销毁时,它会销毁对象,例如“最后一个离开的人会关灯”。

      【讨论】:

        猜你喜欢
        • 2014-06-17
        • 1970-01-01
        • 2016-10-09
        • 1970-01-01
        • 2013-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多