C++ 智能指针(unique_ptr / shared_ptr)代码实现
生活随笔
收集整理的這篇文章主要介紹了
C++ 智能指针(unique_ptr / shared_ptr)代码实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- unique_ptr 智能指針的實現
- shared_ptr 智能指針的實現
- 指針類型轉換
unique_ptr 智能指針的實現
一個對象只能被單個unique_ptr 所擁有。
#include <iostream>using namespace std;/*增加模板類型,保證智能指針的類型是由傳入的類型決定的*/
template <typename T>class smart_ptr {
public:explicit smart_ptr(T *ptr = nullptr): ptr_(ptr){}/*移動構造函數,當前智能指針僅能被一個對象引用*/smart_ptr(smart_ptr&& other) {ptr_ = other.release();}/*如果我們想要消除移動構造和拷貝構造,只需要將其 構造標記為delete*///smart_ptr(const smart_ptr&) = delete;//smart_ptr& operator=(const smart_ptr&) = delete;/*在構造參數時直接生成新的智能指針,從而不再需要在函數體中構造臨時對象,當前支持移動構造進行函數對象的構造。*/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_);}~smart_ptr(){delete ptr_;}T* get() const{ return ptr_;}/*指針的特性,可以通過*解引用訪問 */T& operator*() const{return *ptr_;}/*指針的特性,可以通過-> 訪問指針的地址內容*/T* operator->() const{return ptr_;}/*重載bool運算符,能夠讓smart_ptr像指針一樣用在布爾表達式中*/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; //編譯報錯,賦值需要一個對象(而非引用),因而進入執行之前需要引發一個構造,但是此時沒有可用的構造函數ptr3 = std::move(ptr2); // 編譯正常,支持移動構造 return 0;
}
shared_ptr 智能指針的實現
多個shared_ptr可以共享同一個對象,當他們全部失效的時候,這個對象才會被刪除。
此時對shared_ptr的需求是共享 同一個對象時也需要共享同一個計數,當最后一個指向對象(和共享計數)的shared_ptr析構時,它需要刪除對象和共享計數。
在以上unique_ptr的實現基礎上增加引用計數相關的操作,實現如下:
#include <iostream>using namespace std;/*增加一個引用計數類,來記錄當前對象被智能指針引用的次數*/
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();}}/*移動構造函數,當前智能指針僅能被一個對象引用,同時不進行引用計數的自加*/template <typename U>smart_ptr(smart_ptr<U>&& other) {ptr_ = other.release();if(ptr_) {shared_count_ = other.shared_count_;other.ptr_ = nullptr;}}/*拷貝構造函數,支持子類對象向父類對象的拷貝*/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_;}}/*同類型對象的拷貝構造函數*/smart_ptr(smart_ptr & other) {ptr_ = other.ptr_;if(ptr_) {other.shared_count_ -> add_count();shared_count_ = other.shared_count_;}}/*在構造參數時直接生成新的智能指針,從而不再需要在函數體中構造臨時對象,當前支持移動構造進行函數對象的構造。*/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_;//統計對象引用計數的類
};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); // 移動拷貝構造,不進行計數增加(可查看以上的實現)ptr2 = ptr1; //普通的拷貝構造,支持多個指針共享同一個對象,則對應智能指針的共享計數增加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()
指針類型轉換
C++已有的強制類型轉換有如下幾種:
- static_cast 用于類層次結構中基類和派生類之間指針或引用的轉換
- reinterpret_cast 改變指針或引用的類型、將指針或引用轉換為一個足夠長度的整形、將整型轉換為指針或引用類型
- const_cast 用于強制去掉不能被修改的常數特性
- dynamic_cast dynamic_cast是運行時處理的,運行時要進行類型檢查。
智能指針需要實現類似的函數模板,想要達到以上對應的強制類型轉換的功能,我們需要增加構造函數,且允許在對智能指針內部的指針對象賦值時,使用一個現有的智能指針的共享計數。如下所示:
template <typename U>
smart_ptr(const smart_ptr<U> &other, T* ptr) { //拷貝構造時,使用T* ptr進行類型轉換_ptr = ptr;if(_ptr) {other.shared_count_ -> add_count();shared_count_ = other.shared_count_;}
}
根據以上代碼,實現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;
同理實現其他三個 強制類型轉換的邏輯實現如下:
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);
}
總結
以上是生活随笔為你收集整理的C++ 智能指针(unique_ptr / shared_ptr)代码实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有了女性不孕要如何解决
- 下一篇: 设计模式 之美 -- 原型模式