Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用std::weak\u ptr的共享资源所有权_C++_C++11_Shared Ptr_Smart Pointers_Weak Ptr - Fatal编程技术网

C++ 使用std::weak\u ptr的共享资源所有权

C++ 使用std::weak\u ptr的共享资源所有权,c++,c++11,shared-ptr,smart-pointers,weak-ptr,C++,C++11,Shared Ptr,Smart Pointers,Weak Ptr,我想知道如何(使用C++11并希望使用向后(boost或TR1)兼容的智能指针类型)实现: 一个类实例(ModelController)拥有一个资源(InputConsumer),而另一个组件(InputSender,在本例中是单例)可以访问它 模型是inputssender,它包含对inputsconsumers的引用列表,其中有许多引用 ModelController可能没有、一个或多个inputConsumer,也可能有多个ModelControllers。InputSender不知道 下

我想知道如何(使用C++11并希望使用向后(boost或TR1)兼容的智能指针类型)实现:

一个类实例(
ModelController
)拥有一个资源(
InputConsumer
),而另一个组件(
InputSender
,在本例中是单例)可以访问它

模型是
inputssender
,它包含对
inputsconsumers
的引用列表,其中有许多引用

ModelController
可能没有、一个或多个
inputConsumer
,也可能有多个
ModelController
s。
InputSender
不知道

下面是一个很好的方法:
inputssender
可以跟踪分配给它的
inputcummers
,这样它就可以自己发现单个
inputcummers
是否有效

在我看来,
弱\u ptr
非常适合此用途,因为它们的使用需要检查此条件

如果
inputssender
停止跟踪其
弱的\u ptr
参考,则不会发生任何坏情况,相应的
inputsconsumer
s只会经历无线电静音

如果删除了
ModelController
,或者
ModelController
删除了一些
InputConsumer
s,任何已注册的
InputSender
s将在下次尝试访问它们时识别出它们不再存在,并可以进行清理,不需要发送消息或做任何事情

所以问题是,这是使用
共享ptr
弱ptr
的合适情况吗?我想知道
shared\u ptr
是否完全合适,因为
InputConsumer
s在概念上属于它们的
ModelController
s,所以它们应该是成员变量。我不知道
ModelController
只通过
shared\u ptr
管理它们有多大意义。我不知道
unique\u ptr
是否与
弱\u ptr
一起工作。我应该只管理
ModelController
的ctor/dtor中的
共享\u ptr


这可能也有一个众所周知的(对我来说不是!)设计模式,所以如果有人知道这样的事情,请告诉我。

我在共享指针方面没有很多专业知识,但是是的,这似乎是对
弱\u ptr
的一个非常恰当的使用

在这种情况下,您只是对以下情况感到恼火:

  • 您希望将
    inputcummer
    s直接用作
    ModelController
    s的成员,因为这是一个微不足道的所有权关系
  • 您必须使用
    共享\u ptr
    使其与
    弱\u ptr
    一起工作
  • 我认为这可以通过使用
    共享\u ptr
    作为成员对象的别名来解决。根据:

    此外,共享的\u ptr对象可以共享指针的所有权 同时指向另一个物体。这个能力是 称为别名(参见构造函数),通常用于指向 成员对象,同时拥有它们所属的对象

    我从未亲自做过,但这似乎适合你的情况:

    • 拥有
      InputConsumer
      s
      ModelController
      s的成员
    • 为他们每个人都有一个别名
      共享\u ptr
    • 使用
      弱ptr
      s在
      InputSender
      中引用它们
    编辑

    下面是一个完整的最小工作示例:

    #include <iostream>
    #include <memory>
    
    using namespace std;
    
    // A class to try our smart pointers on
    struct Foo 
    {
        Foo() { cout << "constructing Foo\n"; }
        ~Foo() { cout << "destructing Foo\n"; }
    };
    
    // A class that owns some Foo as members
    struct Owner
    {
        // The actual members
        Foo foo1;
        Foo foo2;
    
        // A fake shared pointer whose purpose is:
        //   1) to be of type shared_ptr<>
        //   2) to have the same lifetime as foo1 and foo2
        shared_ptr<Owner> self;
    
        // A fake deleter that actually deletes nothing 
        struct Deleter
        {
            void operator() (Owner *) { cout << "pretend to delete Owner\n"; }
        };
    
        Owner() : self(this, Deleter()) { cout << "constructing Owner\n"; }
        ~Owner()                        { cout << "destructing Owner\n"; }
    };
    
    // A class that holds a reference to a Foo
    struct Observer
    {
        // A reference to a Foo, as a weak pointer
        weak_ptr<Foo> foo_ptr;
    
        Observer(const shared_ptr<Foo> & foo_ptr) : foo_ptr(foo_ptr)
        {
            cout << "constructing Observer\n";
        }
        ~Observer() { cout << "destructing Observer\n"; }
    
        void check()
        {
            if(foo_ptr.expired())
                cout << "foo expired\n";
            else
                cout << "foo still exists\n";
        }   
    };  
    
    int main()
    {
        // Create Owner, and hence foo1 and foo2
        Owner * owner = new Owner;
    
        // Create an observer, passing an alias of &(owner->foo1) to ctor
        Observer observer(shared_ptr<Foo>(owner->self, &(owner->foo1)));
    
        // Try to access owner->foo1 from observer
        observer.check();
        delete owner;
        observer.check();
    
        return 0;
    }
    
    棘手的部分是能够创建一个到
    所有者->foo1
    弱ptr
    (对于
    foo2
    也是如此)。为此,我们首先需要一个
    shared_ptr
    ,它是
    owner->foo1
    的别名。这只能通过以下方式实现:

    shared_ptr<Foo> alias(other_shared_ptr, &(owner->foo1));
    
    但是,这意味着当
    self
    超出范围时,即在销毁
    owner
    期间,它将调用
    删除此
    。我们不希望发生此删除,否则
    将被删除两次(这是未定义的行为,实际上是SEGFULT)。因此,我们还向
    self
    的构造函数提供了一个实际上不删除任何内容的删除器


    代码的其余部分应该是带有注释的自解释代码。

    再完整一个工作代码段,显示std::weak_ptr dynamics,可能会有更多帮助。(我特别喜欢这个词)

    #包括
    #包括
    #包括
    类消息处理器{
    };
    类消息{
    公众:
    消息(std::shared\u ptr\u msg\u proc,int\u id){
    proc_弱=标准::弱ptr(_msg_proc);
    proc\u shared=\u msg\u proc;
    id=_id;
    }
    std::弱ptr过程弱;
    std::shared_ptr proc_shared;
    int-id;
    };
    int main(){
    std::shared_ptr proc(new MessageProcessor());
    消息消息(proc,1);
    //这里我们有两个共享的proc\u ptr参考:“proc”和“msg.proc\u shared”
    //如预期的“msg.proc_弱未过期”
    如果(!msg.proc_weak.expired())
    
    std::这听起来真的很酷,但我现在还不清楚如何使用别名!你能发布一个小例子吗?谢谢!@StevenLu我以前从未使用过别名,所以我必须了解细节,事实上这比我预期的要复杂。无论如何,这是值得努力的,现在我很好地理解了它们,并且有了一个工作示例t我正在与您共享的内容(请参见编辑)。另一种方法是不使用这些别名,直接让
    共享的\u ptr foo1\u ptr
    所有者的成员,用
    所有者()初始化:foo1\u ptr(新的Foo){}
    ,然后直接使用
    观察者(所有者->foo1\u ptr)
    ,但这会在堆上创建您可能希望避免的数据。我想知道是否有办法避免稍微不体面的伪删除程序。忽略d会造成什么样的破坏
    shared_ptr<Foo> alias(other_shared_ptr, &(owner->foo1));
    
    shared_ptr<Owner> self(this);
    
    #include<iostream>
    #include<memory>
    #include<string>
    
    class MessageProcessor{                
    };
    
    class Message{
    public:
    
            Message(std::shared_ptr<MessageProcessor>  _msg_proc, int _id){
                    proc_weak = std::weak_ptr<MessageProcessor>(_msg_proc);
                    proc_shared = _msg_proc;
                    id = _id;
            }
    
            std::weak_ptr<MessageProcessor> proc_weak;
            std::shared_ptr<MessageProcessor> proc_shared;        
            int id;
    };
    
    int main(){
    
            std::shared_ptr<MessageProcessor> proc(new MessageProcessor());
    
            Message msg(proc,1);
    
            // Here we have proc with 2 shared_ptr refs: 'proc' and 'msg.proc_shared'
            // As expected 'msg.proc_weak is not expired'
            if( !msg.proc_weak.expired() )
                    std::cout << "1) proc_weak is not EXPIRED. proc.use_count() == " << proc.use_count() << std::endl;        
    
            // make one of shared_ptr ref, point to other place
            msg.proc_shared = std::shared_ptr<MessageProcessor>();        
    
            // there is still the 'proc' reference        
            if( !msg.proc_weak.expired() )
                    std::cout << "2) proc_weak is not EXPIRED (yet). proc.use_count() == " << proc.use_count() << std::endl;
    
            // 'erase' the last reference
            proc = std::shared_ptr<MessageProcessor>(); 
    
            // Finally... There is no more refs in shared_pointer!
            if( msg.proc_weak.expired() )
                    std::cout << "3) proc_weak has EXPIRED. proc.use_count() == " << proc.use_count() << std::endl;
    
            return 0; 
    }