C++ 使用模板实现智能指针动态分配

C++ 使用模板实现智能指针动态分配,c++,smart-pointers,C++,Smart Pointers,我正在写一个智能指针计数PTR,我遇到了一个减速。countedptr的基本功能是与任何其他智能指针一样工作,并计算指向单个对象的指针数量。到目前为止,代码是: [已解决] #include "std_lib_facilities.h" template <class T> class counted_ptr{ private: T* pointer; int* count; public: counted_ptr(T* p = 0, int* c = n

我正在写一个智能指针计数PTR,我遇到了一个减速。countedptr的基本功能是与任何其他智能指针一样工作,并计算指向单个对象的指针数量。到目前为止,代码是:

[已解决]

#include "std_lib_facilities.h"

template <class T>
class counted_ptr{
private:
    T* pointer;
    int* count;

public:
    counted_ptr(T* p = 0, int* c = new int(1)) : pointer(p), count(c) {}    // default constructor
    explicit counted_ptr(const counted_ptr& p) : pointer(p.pointer), count(p.count) { ++*count; } // copy constructor
    ~counted_ptr() { --*count; delete pointer; }

    counted_ptr& operator=(const counted_ptr& p)
    {
        pointer = p.pointer;
        count = p.count;
        ++*count;
        return *this;
    }
    T* operator->() const{ return pointer; }
    T& operator*() const { return *pointer; }

    int Get_count() const { return *count; }
};


int main()
{
    counted_ptr<double> one;
    counted_ptr<double>two(one);
    int a = one.Get_count();
    cout << a << endl;
}
然后我得到一个编译器错误,说“请求'*(&one)->counted\u ptr::operator->with T=double'中的成员'pointer',这是非类类型double”

我考虑过用一个函数来实现这一点,虽然我可以用一个函数来分配一个T数组,但我想不出一种方法来分配实际对象。感谢您的帮助。

您的意思是“
one.pointer=new double(5);
”?写入“
one->pointer=new double(5);
”调用
counted\u ptr::operator->
。也就是说,它大致相当于:

double *tmp = one.operator->(); // returns one.pointer
tmp->pointer = new double(5);
但是双指针不是一个结构,因此它没有
指针
成员。

旧的解决方案 另一个赋值操作符呢

counted_ptr& counted_ptr::operator=(T* p)
{
    if (! --*count) { delete count; }
    pointer = p;
    count = new int(1);
    return *this;
}

...

one = new double(5);
此外,析构函数总是删除一个共享指针,这可能是导致*one成为随机名称的原因。也许你想要这样的东西:

counted_ptr::~counted_ptr() { if (! --*count) { delete pointer; delete count; } }
新解决方案 当您想要重新启动计数的ptr(例如
one=new double(5)
)来更新所有相关的
counted\u ptr
s时,将指针和计数都放在一个helper类中,并让您的指针类持有指向helper类的指针(您可能已经沿着此路径前进)。您可以通过两种方式填写此设计:

  • 使helper类成为一个简单的结构(和一个私有的内部类),并将所有逻辑放在外部类方法中
  • 使
    counted\u ptr
    成为助手类<代码>计数\u ptr维护参考计数,但不会自动更新计数;它不是一个智能指针,它只响应
    release
    retain
    消息。如果您对Objective-C非常熟悉,那么这基本上就是它的传统内存管理<当参考计数达到0时(与Obj-C的另一个电位差),code>counted_ptr可能会或可能不会删除自身<代码>计数\u ptrs不应可复制。其目的是,对于任何普通指针,最多应有一个
    计数\u ptr

    创建一个
    smart_ptr
    类,该类有一个指向
    counted_ptr
    的指针,该指针在
    smart_ptr
    实例之间共享,这些实例应该持有相同的普通指针
    smart_ptr
    负责通过发送其
    counted_ptr
    release和retain方法自动更新计数

    counted_ptr
    可能是也可能不是
    共享_ptr
    的私有内部类

  • 这是选项二的界面。因为这是一个练习,所以我将让您填写方法定义。潜在的实现与已经发布的类似,只是您不需要为
    counted\u ptr
    counted\u ptr::~counted\u ptr
    调用
    counted\u ptr::release
    (这是
    smart\u ptr::~smart\u ptr
    的工作)而
    counted\u ptr::release
    可能无法释放
    counted\u ptr::\u指针(您可以将其留给析构函数)

    //counted\u ptr拥有其指针,并将在适当时释放它。
    模板
    类计数{
    私人:
    T*_指针;
    大小和数量;
    //将复制定为非法
    显式计数\u ptr(常数计数\u ptr&);
    计数的\u ptr&运算符=(常数计数的\u ptr&p);
    公众:
    计数的(T*p=0,大小c=1);
    ~uptr();
    void retain();//增加引用计数。
    bool release();//减少引用计数。返回true iff计数为0
    void reassign(T*p);//指向其他对象。
    大小计数()常量;
    计数的ptr和运算符=(T*p);
    T&算子*()常数;
    T*运算符->()常数;
    };
    模板
    类智能ptr{
    私人:
    已计数\u ptr*\u共享;
    void release();//释放共享指针
    void retain();//保留共享指针
    公众:
    smart_ptr(T*p=0,int c=1);//制作一个指向p的smart_ptr
    显式智能\u ptr(计数的\u ptr&p);//生成共享p的智能\u ptr
    显式smart_ptr(smart_ptr&p);//复制构造函数
    ~smart_ptr();
    //注:智能ptr的兄弟是共享计数的智能ptr。
    smart_ptr&operator=(smart_ptr&p);/*加入p的兄弟。不改变预呼叫
    *Brothers.p是非常量的,因为这个->\u shared不能是常量*/
    smart_ptr&operator=(计数的_ptr&p);/*共享p.不会改变兄弟。
    *p是非常量,因为它不是常量*/
    smart_ptr&operator=(T*p);//重新指向此指针。更改
    size\u t count()常量;//引用计数
    T&operator*()const;//将这些委托给_shared
    T*运算符->()常数;
    };
    
    希望上面唯一模棱两可的地方是故意的。

    (对不起,这里是新手,不能留下评论)。Adatapost添加的内容,“
    one=new double(5);
    ”应该可以使用。不过,还需要另一个改变:引用计数需要一些帮助

    ...
    ~counted_ptr() {
        --*count; 
        // deallocate objects whose last reference is gone.
        if (!*count) 
        {   
            delete pointer;
            delete count;
        }
    }
    
    counted_ptr& operator=(const counted_ptr& p)
    {
        // be careful to accommodate self assignment
        ++*p.count;
    
        // may lose a reference here
        --*count;
        if (!*count)
        {
            delete pointer;
            delete count;
        }
    
        count=p.count;
        pointer=p.pointer;
        return *this;
    }
    
    当然,这里有一些代码重复。将代码重构为自己的函数可能是有意义的,例如

    private:
        /** remove our reference */
        void release()
        {
            --*count;
            if (!*count)
            {
                delete pointer;
                delete count;
            }
        }
    

    除非出于学术原因而不这样做,否则您可能想使用“代码> Boo::SyrdYPPTR < /C>”的成员使用“考虑”。它不是完全有效的,但它确实有效,而且您最好使用经过良好测试、成熟且线程安全的工具。如果您是出于学习目的而这样做的,请务必查看中对引用计数和智能指针的处理。

    在覆盖之前,您需要减少计数,并可能删除operator=中指向旧值的指针。在“删除指针”的任何位置,都需要“删除计数”
    ...
    ~counted_ptr() {
        --*count; 
        // deallocate objects whose last reference is gone.
        if (!*count) 
        {   
            delete pointer;
            delete count;
        }
    }
    
    counted_ptr& operator=(const counted_ptr& p)
    {
        // be careful to accommodate self assignment
        ++*p.count;
    
        // may lose a reference here
        --*count;
        if (!*count)
        {
            delete pointer;
            delete count;
        }
    
        count=p.count;
        pointer=p.pointer;
        return *this;
    }
    
    private:
        /** remove our reference */
        void release()
        {
            --*count;
            if (!*count)
            {
                delete pointer;
                delete count;
            }
        }