首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++ 98中的“智能”指针

C++ 98中的“智能”指针
EN

Stack Overflow用户
提问于 2020-08-14 12:03:02
回答 1查看 452关注 0票数 1

我有一个EventEmitter和一个EventHandler对象。将EventHandler*添加到EventEmitter的处理程序矢量中。这使得任何扩展处理程序的对象都可以通过公共接口通过事件发射器进行调用。

现在,当EventHandler决定在程序员没有意识到的情况下进行析构(通常是复制ctors和=运算符),并且EventEmitter最终会调用它,从而导致程序崩溃时,问题就会出现。

第一个想法是为EventHandler提供对其发射器的引用,这样它就可以在销毁过程中调用分离函数。但是,现在我们必须考虑到事件发射器决定死亡,在此之后的任何时间都可以调用处理程序析构函数。我们只是把问题向前推进了。

这听起来像是一个非常常见的指针问题,我不怀疑在C++11或boost中已经解决了这个问题,但我无法访问这两个问题。在C++ 98中,有没有智能指针系统的通用布局可以解决这个问题?

一些用于说明的代码

代码语言:javascript
复制
// Example program
#include <iostream>
#include <string>
#include <vector>

class Handler {
public:
    std::string msg;
    Handler(std::string msg):msg(msg){}
    void Run(){
        std::cout << msg << std::endl;
    }
};

class Emitter {
public:
    std::vector<Handler*> handlers;
    void Attach(Handler *handler){
        handlers.push_back(handler);   
    }
    void Detach(Handler *handler){
        // find the handler, remove
    }
    void Emit(){
        for(size_t i = 0; i < handlers.size(); i++){
            std::cout << "Calling a handler" << std::endl;
            handlers[i]->Run();   
        }
    }
};

int main()
{
    Emitter emitter;
    
    Handler handler1("handler1");
    emitter.Attach(&handler1);
    
    // Uh oh, attached, then out of scope
    {
        Handler handler2("handler2");
        emitter.Attach(&handler2);
    }
    
    emitter.Emit();
        
}

输出

代码语言:javascript
复制
Calling a handler                                                                                                                                           
handler1                                                                                                                                                    
Calling a handler    
EN

回答 1

Stack Overflow用户

发布于 2020-08-14 14:41:08

好的,这就是我想出来的。具有引用计数的共享指针。两个对象共享对这个指针的访问。当它们死亡时,如果引用计数降低到0,它们将删除共享指针。这种情况应该不会多次发生。至少在我的测试中。

代码语言:javascript
复制
// Example program
#include <iostream>
#include <string>
#include <vector>

class SharedPointer {
    public:
        SharedPointer()
            :ref_count(0)
        {
        }
        int ref_count;
};

class Handler {
public:
    SharedPointer *shared_pointer;
    std::string name;
    Handler(std::string name)
        :shared_pointer(NULL),
        name(name)
    {
        std::cout << "Constructing " << name << std::endl;
    }
    ~Handler(){
        std::cout << "Destructing " << name << std::endl;
        // Emitter is still alive
        if(shared_pointer && shared_pointer->ref_count){
            shared_pointer->ref_count--;
            if(!shared_pointer->ref_count){
                delete shared_pointer;
                std::cout << "- - Emitter is dead, so deleting shared ptr " << std::endl;
            }
            else {
                std::cout << "- - Emitter is still alive, so leaving shared ptr " << std::endl;
            }
        }
    }
    void Run(){std::cout<<"Running"<<std::endl;}
};

class SmartHandler {
  public:
    Handler *handler;
    SharedPointer *shared_pointer;
    SmartHandler(Handler *handler, SharedPointer *shared_pointer)
        :handler(handler),
         shared_pointer(shared_pointer)
    {
        handler->shared_pointer = shared_pointer;
        handler->shared_pointer->ref_count++;
    }
};

class Emitter {
public:
    std::vector<SmartHandler> handlers;
    ~Emitter(){
        for(size_t i = 0; i < handlers.size(); i++){
            std::cout << "Removing a handler" << std::endl;
            if(handlers[i].shared_pointer && handlers[i].shared_pointer->ref_count){
                handlers[i].shared_pointer->ref_count--;
                if(!handlers[i].shared_pointer->ref_count){
                    delete handlers[i].shared_pointer;
                    std::cout << "- - Handler is dead, so deleting shared ptr " << std::endl;
                }
                else {
                    std::cout << "- - " << handlers[i].handler->name << " is still alive, so leaving shared ptr " << std::endl;
                }
            }
        }
    }
    void Attach(Handler *handler){
        SharedPointer *shared_pointer = new SharedPointer();
        shared_pointer->ref_count++;
        SmartHandler smart_handler(handler, shared_pointer);
        handlers.push_back(smart_handler);  
    }
    void Detach(Handler *handler){
        // find the handler, remove
    }
    void Emit(){
        for(size_t i = 0; i < handlers.size(); i++){
            if(handlers[i].handler && handlers[i].shared_pointer->ref_count > 1){
                std::cout << "Calling Run() for handler " << handlers[i].handler->name << std::endl;
                handlers[i].handler->Run();
            }
            else{
                std::cout << "This handler appears to be dead" << std::endl;   
            }
        }
    }
};

int main()
{
    Handler h_scope_1("h_scope_1");
    {
        Emitter emitter;
        emitter.Attach(&h_scope_1);
        
        Handler h_scope_2("h_scope_2");
        emitter.Attach(&h_scope_2);
        
        {
            Handler h_scope_3("h_scope_3");
            emitter.Attach(&h_scope_3);
        }
        
        emitter.Emit();
    }
}

输出

代码语言:javascript
复制
Constructing h_scope_1                                                                                                                                        
Constructing h_scope_2                                                                                                                                        
Constructing h_scope_3                                                                                                                                        
Destructing h_scope_3                                                                                                                                         
- - Emitter is still alive, so leaving shared ptr                                                                                                             
Calling Run() for handler h_scope_1                                                                                                                           
Running                                                                                                                                                       
Calling Run() for handler h_scope_2                                                                                                                           
Running                                                                                                                                                       
This handler appears to be dead                                                                                                                               
Destructing h_scope_2                                                                                                                                         
- - Emitter is still alive, so leaving shared ptr                                                                                                             
Removing a handler                                                                                                                                            
- - h_scope_1 is still alive, so leaving shared ptr                                                                                                           
Removing a handler                                                                                                                                            
- - Handler is dead, so deleting shared ptr                                                                                                                   
Removing a handler                                                                                                                                            
- - Handler is dead, so deleting shared ptr                                                                                                                   
Destructing h_scope_1                                                                                                                                         
- - Emitter is dead, so deleting shared ptr   
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63406345

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档