如何在现代c ++中创建外部管理对象的数组或列表?

时间:2017-08-14 16:24:51

标签: c++ memory-management

我正在为程序构建一个加载项。我的加载项操作宿主应用程序传递给我的Ptr对象。我想创建一个由主机创建的外部创建和管理对象的向量。不幸的是,文档没有任何明确的示例如何执行此操作。

class Players {
    vector<Ptr<Player>> vectorOfGamers; // who deletes and when this? 

    public void CreatePlayers () {
    // call static application to create three players
    for ( int i = 0; i < 3; i++ )
       vectorOfGamers.push_back(Application.GetNextPlayer()); 
     } 

}

如果构建此类并防止内存泄漏并在项目过早删除时导致空异常,则会感到困惑。另外,我如何使用现代C ++工具来实现这一目标,同时获得新内存管理的好处,如make_shared,make_unique,nullptr等?

为了您的信息,下面是Ptr的快照。我对Ptr感到困惑,因为它看起来多余,因为现代C ++的新内存管理设施。

class IncompleteType
{
public:
    template<typename T> static void addref(void* ptr) { reinterpret_cast<adsk::core::ReferenceCounted*>(ptr)->addref(); }
    template<typename T> static void release(void* ptr) { reinterpret_cast<adsk::core::ReferenceCounted*>(ptr)->release(); }
};

class CompleteType
{
public:
    template<typename T> static void addref(T* ptr) { ptr->addref(); }
    template<typename T> static void release(T* ptr) { ptr->release(); }
};

template<class T, class PT = IncompleteType>
class Ptr
{
public:

    typedef T element_type;

    Ptr() : ptr_(nullptr) {}
    Ptr(const Ptr& rhs) : ptr_(nullptr) { reset(rhs.ptr_); }
    Ptr(const T* ptr, bool attach = true) : ptr_(nullptr) { reset(ptr, attach); }

    // casting constructor.  call operator bool to verify if cast was successful
    template<class V, class VPT>
    Ptr(const Ptr<V, VPT>& rhs) : ptr_(nullptr) {
        if (rhs)
            reset(rhs->template query<T>(), false);
    }

    ~Ptr() { reset(nullptr); }

    void operator=(const Ptr<T, PT>& rhs) { if (&rhs != this) reset(rhs.ptr_); }
    void operator=(const T* ptr) { reset(ptr, true); }

    // casting assignment operator.  call operator bool to verify if cast was successful
    template<class V, class VPT>
    void operator=(const Ptr<V, VPT>& rhs) {
        if (rhs)
            reset(rhs->template query<T>(), false);
        else
            reset(nullptr);
    }

    void reset(const T* ptr, bool attach = false) {
        if (ptr_ != ptr)
        {
            if (ptr_)
                PT::template release<T>(ptr_);
            ptr_ = const_cast<T*>(ptr);
            if (!attach && ptr_)
                PT::template addref<T>(ptr_);
        }
    }

    T* operator->() const { assert(ptr_ != nullptr); if (ptr_ == nullptr) throw std::exception(); return ptr_; }

    // Test if this pointer is empty (if operator-> will throw)
    /*explicit*/ operator bool() const { return ptr_ != nullptr; }

    bool operator==(const Ptr& rhs) const { return ptr_ == rhs.ptr_; }
    bool operator!=(const Ptr& rhs) const { return ptr_ != rhs.ptr_; }
    bool operator<(const Ptr& rhs) const { return ptr_ < rhs.ptr_; }


    // Iteration support.  Only usable if T has count and item members and an iterable_type
    typedef Iterator<T, PT> iterator;
    iterator begin() const { return Iterator<T, PT>(*this); }
    iterator end() const { return Iterator<T, PT>(*this, true); }

    // Caution the following functions if used incorrectly can cause a reference count leak
    T* get() const { return ptr_; }
    T* detach() { T* t = ptr_; ptr_ = nullptr; return t; }

private:

    T* ptr_;
};

1 个答案:

答案 0 :(得分:1)

你可能是正确的,在后C ++ 03环境中不需要Ptr。可能你的插件API已经足够老了,C ++ 11就不存在了。从您发布的代码中我最好的猜测是Ptr应该是一个引用计数的智能指针,它管理像std::shared_ptr这样的共享所有权。

您应该从plguin API文档以及主机程序的源代码中清楚地了解到这一点。只是从你发布的片段中,甚至没有提到程序的名称,就不可能说清楚了。