Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.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++ 由支持多态性的值池存储,如何使用智能指针? 介绍_C++_Polymorphism_Smart Pointers_Pool - Fatal编程技术网

C++ 由支持多态性的值池存储,如何使用智能指针? 介绍

C++ 由支持多态性的值池存储,如何使用智能指针? 介绍,c++,polymorphism,smart-pointers,pool,C++,Polymorphism,Smart Pointers,Pool,我有一个数据结构:值池。(不是指针池) 当我调用create()时,它将返回Handle 到目前为止一切都很好 template<class T> class Pool{ std::vector<T> v; //store by value Handle<T> create(){ .... } } template<class T> class Handle{ Pool<T>

我有一个数据结构:值池。(不是指针池)

当我调用create()时,它将返回Handle

到目前为止一切都很好

template<class T> class Pool{
    std::vector<T> v;                   //store by value
    Handle<T> create(){  .... }
}
template<class T> class Handle{
    Pool<T>* pool_;                    //pointer back to container
    int pool_index_;                   //where I am in the container
    T* operator->() {                  
        return pool_->v.at(pool_index_);     //i.e. "pool[index]"
    }
    void destroy(){
        pool_-> ... destroy(this)  .... mark "pool_index_" as unused, etc ....
    }
}
模板类池{
std::vector v;//按值存储
句柄create(){..}
}
模板类句柄{
Pool*Pool;//指向容器的指针
int pool_index;//我在容器中的位置
T*运算符->(){
返回pool->v.at(pool_index);//即“pool[index]”
}
无效销毁(){
池->…销毁(此)…将“池索引”标记为未使用,等等。。。。
}
}
现在我想要句柄来支持多态性

问题: 很多专家都建议我使用弱ptr,但我还是一个星期没用了,不知道怎么做

我卡住的主要部件是:-

  • 是否应该创建()返回弱ptr,而不是处理? .... 还是应该处理封装弱\u ptr

  • 如果create()返回用户程序的弱ptr。。。 弱的ptr如何知道集合指数?它没有这样的字段

  • 如果用户按如下方式将弱\u ptr/句柄转换为父类指针,则会出现许多问题:-

e、 g

B类{}
C类:公共B{。。。。。。
}
....
{
池cs;
句柄cPtr=cs.create();
句柄bPtr=cPtr;//强制转换;应为有效,
//…但如何解决?(弱ptr可能会解决)
bPtr->destroy();//aPtr将调用Pool::destroy,这是错误的!
//销毁是正确的
bPtr.operator->();//面临与上面相同的问题
}
假设
  • 池总是在句柄之后被删除(为了简单起见)
  • 没有多线程
这里有一些类似的问题,但没有一个足够接近。

关于
弱\u ptr
std::weak_ptr
始终与
std::shared_ptr
关联。要使用
弱\u ptr
,您必须使用
共享\u ptr
管理对象。这意味着可以共享对象的所有权:任何人都可以从
弱ptr
构建
共享ptr
,并将其存储在某处。只有当所有
共享的\u ptr
被销毁时,指向的对象才会被删除。
池将失去对对象释放的直接控制,因此无法支持公共
销毁()
功能。
共享所有权会让事情变得一团糟

这就是为什么
std::unique\u ptr
通常是对象生命周期管理的更好选择的原因之一(遗憾的是,它不适用于
弱\u ptr
)。您的
Handle::destroy()
函数还意味着这不是您想要的,并且
池本身应该处理其对象的生存期

但是,
shared_ptr
/
weak_ptr
是为多线程应用程序设计的。在单线程环境中,您可以获得类似于
弱ptr
的功能(检查有效目标并避免挂起指针),而无需使用
弱ptr

template<class T> class Pool {
    bool isAlive(int index) const { ... }
}

template<class T> class Handle {
    explicit operator bool() const { return pool_->isAlive(pool_index_); }
}
在多次取消引用句柄时,仍然必须小心。例如:

void doDamage(Handle<GameUnit> source, Handle<GameUnit> target) {    
    if(source && target) {
        source->invokeAction(target);
        // What if 'target' reflects some damage back and kills 'source'?
        source->payMana(); // Segfault
    }
}
用法:

Pool<Impl> pool;
Handle<Impl> impl = pool.create();

// Conversions
Handle<Base> base  = impl; // Works
Handle<Impl> impl2 = base; // Compile error - which is expected
Pool;
Handle impl=pool.create();
//转换
Handle base=impl;//作品
句柄impl2=base;//编译错误-这是预期错误
检查有效转换的行可能会被优化掉。检查仍将在编译时进行!尝试无效转换将导致如下错误:

错误:从“Base*”到“Impl*”[-fppermissive]的转换无效
T*不能转换句柄=(D*)空ptr

我在这里上传了一个简单的可编译测试用例:

void doSomething(Handle<Obj> handle) {
    if(handle) {
        // No other threads can interfere
        handle->doIt();
    }
}
void doDamage(Handle<GameUnit> source, Handle<GameUnit> target) {    
    if(source && target) {
        source->invokeAction(target);
        // What if 'target' reflects some damage back and kills 'source'?
        source->payMana(); // Segfault
    }
}
struct PoolBase {
    virtual void destroy(int index)       = 0;
    virtual void* get(int index)          = 0;
    virtual bool isAlive(int index) const = 0;
};

template<class T> struct Pool : public PoolBase {
    Handle<T> create() { return Handle<T>(this, nextIndex); }
    void destroy(int index) override { ... }
    void* get(int index) override { ... }
    bool isAlive(int index) const override { ... }
};

template<class T> struct Handle {
    PoolBase* pool_;
    int pool_index_;

    Handle(PoolBase* pool, int index) : pool_(pool), pool_index_(index) {}

    // Conversion Constructor
    template<class D> Handle(const Handle<D>& orig) {
        T* Cannot_cast_Handle = (D*)nullptr;
        (void)Cannot_cast_Handle;

        pool_ = orig.pool_;
        pool_index_ = orig.pool_index_;
    }

    explicit operator bool() const { return pool_->isAlive(pool_index_); }
    T* operator->() { return static_cast<T*>( pool_->get(pool_index_) ); }
    void destroy() { pool_->destroy(pool_index_); }
};
Pool<Impl> pool;
Handle<Impl> impl = pool.create();

// Conversions
Handle<Base> base  = impl; // Works
Handle<Impl> impl2 = base; // Compile error - which is expected