C++ 使用模板实现智能指针动态分配
我正在写一个智能指针计数PTR,我遇到了一个减速。countedptr的基本功能是与任何其他智能指针一样工作,并计算指向单个对象的指针数量。到目前为止,代码是: [已解决]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
#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类的指针(您可能已经沿着此路径前进)。您可以通过两种方式填写此设计:
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;
}
}