文章目錄
- 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);
}
使用方式如下:
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);
}