C++ 智能指针(unique_ptr / shared_ptr)代码实现
文章目錄
- unique_ptr 智能指針的實(shí)現(xiàn)
- shared_ptr 智能指針的實(shí)現(xiàn)
- 指針類型轉(zhuǎn)換
unique_ptr 智能指針的實(shí)現(xiàn)
一個對象只能被單個unique_ptr 所擁有。
#include <iostream>using namespace std;/*增加模板類型,保證智能指針的類型是由傳入的類型決定的*/
template <typename T>class smart_ptr {
public:explicit smart_ptr(T *ptr = nullptr): ptr_(ptr){}/*移動構(gòu)造函數(shù),當(dāng)前智能指針僅能被一個對象引用*/smart_ptr(smart_ptr&& other) {ptr_ = other.release();}/*如果我們想要消除移動構(gòu)造和拷貝構(gòu)造,只需要將其 構(gòu)造標(biāo)記為delete*///smart_ptr(const smart_ptr&) = delete;//smart_ptr& operator=(const smart_ptr&) = delete;/*在構(gòu)造參數(shù)時直接生成新的智能指針,從而不再需要在函數(shù)體中構(gòu)造臨時對象,當(dāng)前支持移動構(gòu)造進(jìn)行函數(shù)對象的構(gòu)造。*/smart_ptr& operator=(smart_ptr rhs) {rhs.swap(*this);return *this;} T* release() {T* ptr = ptr_;ptr_ = nullptr;return ptr;}void swap(smart_ptr& rhs) {using std::swap;//標(biāo)準(zhǔn)模板庫的交換函數(shù)swap(rhs.ptr_,ptr_);}~smart_ptr(){delete ptr_;}T* get() const{ return ptr_;}/*指針的特性,可以通過*解引用訪問 */T& operator*() const{return *ptr_;}/*指針的特性,可以通過-> 訪問指針的地址內(nèi)容*/T* operator->() const{return ptr_;}/*重載bool運(yùn)算符,能夠讓smart_ptr像指針一樣用在布爾表達(dá)式中*/operator bool() const{return ptr_;}private:T* ptr_;
};class Shape{public:virtual void create_shape() = 0;virtual ~Shape(){}
};class Circle: public Shape{public:Circle(){cout << "Circle::Circle()" << endl;}void create_shape(){cout << "create shape: Circle" << endl;}~Circle(){cout << "Circle::delete()" << endl;}
};class Triangle: public Shape{public:Triangle(){cout << "Triangle::Tirangle()" << endl;}void create_shape(){cout << "create shape: Triangle" << endl;}~Triangle(){cout << "Triangle::delete()" << endl;}
};int main()
{smart_ptr<Shape> ptr1(new Circle);smart_ptr<Shape> ptr2(nullptr);smart_ptr<Shape> ptr3 ;//ptr3 = ptr1; //編譯報錯,賦值需要一個對象(而非引用),因而進(jìn)入執(zhí)行之前需要引發(fā)一個構(gòu)造,但是此時沒有可用的構(gòu)造函數(shù)ptr3 = std::move(ptr2); // 編譯正常,支持移動構(gòu)造 return 0;
}
shared_ptr 智能指針的實(shí)現(xiàn)
多個shared_ptr可以共享同一個對象,當(dāng)他們?nèi)渴У臅r候,這個對象才會被刪除。
此時對shared_ptr的需求是共享 同一個對象時也需要共享同一個計數(shù),當(dāng)最后一個指向?qū)ο?#xff08;和共享計數(shù))的shared_ptr析構(gòu)時,它需要刪除對象和共享計數(shù)。
在以上unique_ptr的實(shí)現(xiàn)基礎(chǔ)上增加引用計數(shù)相關(guān)的操作,實(shí)現(xiàn)如下:
#include <iostream>using namespace std;/*增加一個引用計數(shù)類,來記錄當(dāng)前對象被智能指針引用的次數(shù)*/
class shared_count{
public:shared_count():count_(1) {}void add_count(){++count_;}long reduce_count(){return --count_;}long get_count() {return count_;}
private:long count_;
};/*增加類模板,保證智能指針的類型是由傳入的類型決定的*/
template <typename T>class smart_ptr {
public:explicit smart_ptr(T *ptr = nullptr): ptr_(ptr){if(ptr) {shared_count_ = new shared_count();}}/*移動構(gòu)造函數(shù),當(dāng)前智能指針僅能被一個對象引用,同時不進(jìn)行引用計數(shù)的自加*/template <typename U>smart_ptr(smart_ptr<U>&& other) {ptr_ = other.release();if(ptr_) {shared_count_ = other.shared_count_;other.ptr_ = nullptr;}}/*拷貝構(gòu)造函數(shù),支持子類對象向父類對象的拷貝*/template <typename U>smart_ptr(const smart_ptr<U>& other) {ptr_ = other.ptr_;if(ptr_) {other.shared_count_ -> add_count();shared_count_ = other.shared_count_;}}/*同類型對象的拷貝構(gòu)造函數(shù)*/smart_ptr(smart_ptr & other) {ptr_ = other.ptr_;if(ptr_) {other.shared_count_ -> add_count();shared_count_ = other.shared_count_;}}/*在構(gòu)造參數(shù)時直接生成新的智能指針,從而不再需要在函數(shù)體中構(gòu)造臨時對象,當(dāng)前支持移動構(gòu)造進(jìn)行函數(shù)對象的構(gòu)造。*/smart_ptr& operator=(smart_ptr rhs) {rhs.swap(*this);return *this;} T* release() {T* ptr = ptr_;ptr_ = nullptr;return ptr;}void swap(smart_ptr& rhs) {using std::swap;swap(rhs.ptr_,ptr_);swap(rhs.shared_count_,shared_count_);}long use_count() const {if(ptr_) {return shared_count_->get_count();} else {return 0;}}~smart_ptr(){// cout << "smart_ptr::delete count is " << shared_count_ -> get_count() << endl;if(ptr_ && !shared_count_ -> reduce_count()){delete ptr_;delete shared_count_;}}T* get() const{ return ptr_;}T& operator*() const{return *ptr_;}T* operator->() const{return ptr_;}operator bool() const{return ptr_;}private:T* ptr_;shared_count* shared_count_;//統(tǒng)計對象引用計數(shù)的類
};class Shape{public:virtual void create_shape() = 0;virtual ~Shape(){}
};class Circle: public Shape{public:Circle(){cout << "Circle::Circle()" << endl;}void create_shape(){cout << "create shape: Circle" << endl;}~Circle(){cout << "Circle::delete()" << endl;}
};class Triangle: public Shape{public:Triangle(){cout << "Triangle::Tirangle()" << endl;}void create_shape(){cout << "create shape: Triangle" << endl;}~Triangle(){cout << "Triangle::delete()" << endl;}
};int main()
{smart_ptr<Shape> ptr1(new Circle);cout << "use count of ptr1 is: " << ptr1.use_count() << endl;smart_ptr<Shape> ptr2;cout << "use count of ptr2 was: " << ptr2.use_count() << endl;//ptr2 = std::move(ptr1); // 移動拷貝構(gòu)造,不進(jìn)行計數(shù)增加(可查看以上的實(shí)現(xiàn))ptr2 = ptr1; //普通的拷貝構(gòu)造,支持多個指針共享同一個對象,則對應(yīng)智能指針的共享計數(shù)增加cout << "use count of ptr2 is now: " << ptr2.use_count() << endl;if(ptr1) {cout << "ptr1 is not empty " << endl; }return 0;
}
輸出如下:
Circle::Circle()
use count of ptr1 is: 1
use count of ptr2 was: 0
use count of ptr2 is now: 2
Circle::delete()
指針類型轉(zhuǎn)換
C++已有的強(qiáng)制類型轉(zhuǎn)換有如下幾種:
- static_cast 用于類層次結(jié)構(gòu)中基類和派生類之間指針或引用的轉(zhuǎn)換
- reinterpret_cast 改變指針或引用的類型、將指針或引用轉(zhuǎn)換為一個足夠長度的整形、將整型轉(zhuǎn)換為指針或引用類型
- const_cast 用于強(qiáng)制去掉不能被修改的常數(shù)特性
- dynamic_cast dynamic_cast是運(yùn)行時處理的,運(yùn)行時要進(jìn)行類型檢查。
智能指針需要實(shí)現(xiàn)類似的函數(shù)模板,想要達(dá)到以上對應(yīng)的強(qiáng)制類型轉(zhuǎn)換的功能,我們需要增加構(gòu)造函數(shù),且允許在對智能指針內(nèi)部的指針對象賦值時,使用一個現(xiàn)有的智能指針的共享計數(shù)。如下所示:
template <typename U>
smart_ptr(const smart_ptr<U> &other, T* ptr) { //拷貝構(gòu)造時,使用T* ptr進(jìn)行類型轉(zhuǎn)換_ptr = ptr;if(_ptr) {other.shared_count_ -> add_count();shared_count_ = other.shared_count_;}
}
根據(jù)以上代碼,實(shí)現(xiàn)dynamic_pointer_cast
template <typename T, typename U>
smart_ptr <T> dynamic_pointer_cast(const smart_ptr<U> &other) {T *ptr = dynamic_cast<T*> (other.get());return smart_ptr<T> (other,ptr);
}
使用方式如下:
smart_ptr<Circle> ptr3 = dynamic_pointer_cast<Circle> ptr2;
同理實(shí)現(xiàn)其他三個 強(qiáng)制類型轉(zhuǎn)換的邏輯實(shí)現(xiàn)如下:
template <typename T, typename U>
smart_ptr <T> static_pointer_cast(const smart_ptr<U> &other) {T *ptr = static_cast<T*> (other.get());return smart_ptr<T> (other,ptr);
}template <typename T, typename U>
smart_ptr <T> reinterpret_pointer_cast(const smart_ptr<U> &other) {T *ptr = reinterpret_cast<T*> (other.get());return smart_ptr<T> (other,ptr);
}template <typename T, typename U>
smart_ptr <T> const_pointer_cast(const smart_ptr<U> &other) {T *ptr = const_cast<T*> (other.get());return smart_ptr<T> (other,ptr);
}
總結(jié)
以上是生活随笔為你收集整理的C++ 智能指针(unique_ptr / shared_ptr)代码实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有了女性不孕要如何解决
- 下一篇: 设计模式 之美 -- 原型模式