C++ 智能指针类的简单实现
在《C++初级读物13.5.1》一书中,它使用一个使用计数类实现了一个智能指针类。其实施情况如下:C++ 智能指针类的简单实现,c++,copy-constructor,smart-pointers,C++,Copy Constructor,Smart Pointers,在《C++初级读物13.5.1》一书中,它使用一个使用计数类实现了一个智能指针类。其实施情况如下: 使用计数类 // private class for use by HasPtr only class U_Ptr { friend class HasPtr; int *ip; size_t use; U_Ptr(int *p): ip(p), use(1) { } ~U_Ptr() { delete ip; } }; 智能指针类 /* sm
- 使用计数类
// private class for use by HasPtr only class U_Ptr { friend class HasPtr; int *ip; size_t use; U_Ptr(int *p): ip(p), use(1) { } ~U_Ptr() { delete ip; } };
- 智能指针类
/* smart pointer class: takes ownership of the dynamically allocated object to which it is bound User code must dynamically allocate an object to initialize a HasPtr and must not delete that object; the HasPtr class will delete it */ class HasPtr { public: // HasPtr owns the pointer; p must have been dynamically allocated HasPtr(int *p, int i) : ptr(new U_Ptr(p)), val(i) { } // copy members and increment the use count HasPtr(const HasPtr &orig) : ptr(orig.ptr), val(orig.val) { ++ptr->use; } HasPtr& operator=(const HasPtr&); // if use count goes to zero, delete the U_Ptr object ~HasPtr() { if (--ptr->use == 0) delete ptr; } friend ostream& operator<<(ostream&, const HasPtr&); // copy control and constructors as before // accessors must change to fetch value from U_Ptr object int *get_ptr() const { return ptr->ip; } int get_int() const { return val; } // change the appropriate data member void set_ptr(int *p) { ptr->ip = p; } void set_int(int i) { val = i; } // return or change the value pointed to, so ok for const objects // Note: *ptr->ip is equivalent to *(ptr->ip) int get_ptr_val() const { return *ptr->ip; } void set_ptr_val(int i) { *ptr->ip = i; } private: U_Ptr *ptr; // points to use-counted U_Ptr class int val; };
测试:我使用如下代码测试了上述
,它似乎运行良好智能指针类
int main() { T t1; T t2(t1); T t3(t1); T t4; t4 = t1; return 0; }
真正的问题:这个新的
,只需一个智能指针类
就足够了吗?如果是,为什么还要像书中那样使用额外的int*countPtr
use Count类呢?如果否,我会错过什么?原始实现的一个属性是在控制块对象中使用原始指针类型执行
删除。这是部分类型擦除。无论复制了多少智能指针对象,但类型有所不同,原始控制块保持不变,通过原始指针类型执行
但是,由于您显示的原始代码不是模板化的,因此必须假定它是早期的示例,随后是类似的模板化代码 在基类层次结构中向上转换指针,就像复制智能指针一样,意味着只有静态已知的新类型具有虚拟析构函数时,新指针类型上的delete
才有效delete
例如,
也会通过原始指针类型删除(保证),除非明确提供执行其他操作的deleter functor。您的代码与本书中报告的标准代码等效。然而,在某些方面它是最糟糕的:std::shared\u ptr
- 您需要两个分配/解除分配而不是一个(两个整数而不是一个对象)。这可能会更慢,也更难管理
- 每个对象中都有一个指针副本。所以:重复的信息,你应该保证保持有效
- 对象较大(两个指针而不是一个指针)
你只有一个积极的方面:- 对指针的访问是直接的,而不是间接的。这可能意味着使用您的实现对引用对象的访问会稍微快一点
我的猜测是,作者——无论是有意识的还是潜意识的——意识到在现实世界的智能指针中有一个单独的类是有用的,例如:- 弱指针的计数(不确定您是否听说过它们-它们跟踪对象而不延长其生命周期,这样您可以稍后尝试将其转换为(正常)共享指针,但只有在至少有一个指向对象的共享指针使其保持活动状态时,它才起作用)
- 使共享指针线程安全的互斥锁(尽管原子操作在可用时可能更好)
- 调试信息(例如boost::shared#ptr有一个#ifdef以包含一个共享计数器id)
- 虚拟调度表,由boost共享指针等使用,以调度到操作系统相应的代码(请参阅boost/smart_ptr/detail/sp_counted_base_*.hpp标头)
…(2017年4月14日更新) 我自己尝试了unique_ptr和shared_ptr,但有点惊讶地发现这些课程并没有让你的生活更轻松。我在一个API中有一个函数,函数将拾取U_Ptr
-填写它(指针),然后需要删除该对象。可以使用c++11,但您需要为此添加额外的临时指针。(所以使用*ptr类并不会让我的生活更轻松) 实现智能指针有多复杂 通过快速浏览auto_ptr类实现,我已经快速编写了简单的智能点容器类,但是我注意到我需要支持引用同一对象指针的多个智能指针 好的,那么编码引用计数会有多复杂呢?我通过,然后去了谷歌,找到了一篇关于它的有趣文章: 不知何故,我倾向于同意那篇文章的作者和那篇文章中的评论,引用计数使生活变得更加复杂,但仍然试图坚持使用纯C也听起来有点愚蠢 现在,我将在这里添加我自己的类的代码片段,如果您想获得最新版本,可以签入此svn存储库: 下面是旧版本对象*&
#pragma once // // If you're using multithreading, please make sure that two threads are not accessing // SmartPtr<> pointers which are cross linked. // template <class T> class SmartPtr { public: SmartPtr() : ptr( nullptr ), next( nullptr ) { } SmartPtr( T* pt ) : ptr( pt ), next( nullptr ) { } SmartPtr( SmartPtr<T>& sp ) : ptr( nullptr ), next( nullptr ) { operator=(sp); } ~SmartPtr() { release(); } // Reference to pointer - assumed to be filled out by user. T*& refptr() { release(); return ptr; } // Pointer itself, assumed to be used. T* get() { return ptr; } T* operator->() const { return ptr; } T* operator=( T* _ptr ) { release(); ptr = _ptr; return ptr; } SmartPtr<T>& operator=( SmartPtr<T>& sp ) { release(); ptr = sp.ptr; if ( ptr ) // If we have valid pointer, share ownership. { if( sp.next == nullptr ) { next = &sp; sp.next = this; } else { SmartPtr<T>* it = &sp; while( it->next != &sp ) it = it->next; next = &sp; it->next = this; } } return *this; } void release() { if ( !ptr ) return; // Shared ownership. if( next != nullptr ) { // Remove myself from shared pointer list. SmartPtr<T>* it = next; while( it->next != this ) it = it->next; if( it == it->next->next ) it->next = nullptr; else it->next = next; next = nullptr; ptr = nullptr; return; } // Single user. delete ptr; ptr = nullptr; } T* ptr; // pointer to object SmartPtr<T>* next; // nullptr if pointer is not shared with anyone, // otherwise cyclic linked list of all SmartPtr referencing that pointer. };
#pragma一次 // //如果您使用的是多线程,请确保没有两个线程访问 //交叉链接的SmartPtr指针。 // 模板 类SmartPtr { 公众: SmartPtr():ptr(nullptr),next(nullptr) { } 智能ptr(T*pt):ptr(pt),next(nullptr) { } SmartPtr(SmartPtr&sp):ptr(nullptr),next(nullptr) { 运算符=(sp); } ~SmartPtr() { 释放(); } //指针引用-假定由用户填写。 T*&refptr() { 释放(); 返回ptr; } //假定要使用的指针本身。 T*get() { 返回ptr; } T*运算符->()常量 { 返回ptr; } T*运算符=(T*_ptr) { 释放(); ptr=_ptr; 返回ptr; } SmartPtr和操作员=(SmartPtr和sp) { 释放(); ptr=sp.ptr; if(ptr)//如果我们有有效的指针,则共享所有权。 { 如果(sp.next==nullptr) { 下一步=&sp; sp.next=此; }否则{ SmartPtr*it=&sp; while(it->next!=&sp) it=it->next; 下一步=&sp; it->next=这个; } } 返回
#pragma once // // If you're using multithreading, please make sure that two threads are not accessing // SmartPtr<> pointers which are cross linked. // template <class T> class SmartPtr { public: SmartPtr() : ptr( nullptr ), next( nullptr ) { } SmartPtr( T* pt ) : ptr( pt ), next( nullptr ) { } SmartPtr( SmartPtr<T>& sp ) : ptr( nullptr ), next( nullptr ) { operator=(sp); } ~SmartPtr() { release(); } // Reference to pointer - assumed to be filled out by user. T*& refptr() { release(); return ptr; } // Pointer itself, assumed to be used. T* get() { return ptr; } T* operator->() const { return ptr; } T* operator=( T* _ptr ) { release(); ptr = _ptr; return ptr; } SmartPtr<T>& operator=( SmartPtr<T>& sp ) { release(); ptr = sp.ptr; if ( ptr ) // If we have valid pointer, share ownership. { if( sp.next == nullptr ) { next = &sp; sp.next = this; } else { SmartPtr<T>* it = &sp; while( it->next != &sp ) it = it->next; next = &sp; it->next = this; } } return *this; } void release() { if ( !ptr ) return; // Shared ownership. if( next != nullptr ) { // Remove myself from shared pointer list. SmartPtr<T>* it = next; while( it->next != this ) it = it->next; if( it == it->next->next ) it->next = nullptr; else it->next = next; next = nullptr; ptr = nullptr; return; } // Single user. delete ptr; ptr = nullptr; } T* ptr; // pointer to object SmartPtr<T>* next; // nullptr if pointer is not shared with anyone, // otherwise cyclic linked list of all SmartPtr referencing that pointer. };