智能指針的簡單實現
在c++中對指針的操作是一件很麻煩的事,因此智能指針應運而生,智能指針使我們在new一個對象的時候不用關心它的釋放。首先我們要對指針有一定的了解,指針中最常見的行為便是內容提領(dereference)和成員訪問(mermber access)。所謂的智能指針其實是一個將原始指針封裝在一個類中,此類中重載了*和->運算符,其中*運算符的重載便實現了內容提領,而->運算符便實現了成員訪問。c++標准庫中提供了auto_ptr,今天我們來簡單的實現它。
首先編寫my_auto_ptr.h文件:
#ifndef MY_AUTO_PTR
#define MY_AUTO_PTR
// 智能指針的目的就是行為類似指針但是又不用手動delete釋放內存,為編程提供便利
// 出於此目的進行程序編寫
template<class T>
class my_auto_ptr {
public:
explicit my_auto_ptr(T* p = nullptr) :ptr(p) {} // 構造函數
template<class U> // 一旦被拷貝就將以前的指針賦值為nullptr
my_auto_ptr(my_auto_ptr<U>& rhs) :ptr(rhs.release()){} // 復制構造函數
template<class U>
my_auto_ptr<U>& operator=(my_auto_ptr<U>& rhs) {
if (this != &rhs) { // this本來就是一個指針,指向調用對象
reset(rhs.release());
}
return *this;
}
T* get() const {
return ptr;
}
T& operator*() const {
return *ptr;
}
T* operator->() const { // 可以實現成員訪問
return ptr;
}
~my_auto_ptr() {
delete ptr;
}
T* release() { // 將指針值置0 內存的釋放由析構函數完成
T* tmp = ptr;
ptr = nullptr;
return tmp;
}
void reset(T* p) { // 重新指向新的區域
if (p != ptr) {
delete ptr;
}
ptr = p;
}
private:
T* ptr;
};
#endif // !MY_AUTO_PTR
接下來是測試程序,讓我們一起一探究竟:
#include <iostream>
#include "my_auto_ptr.h"
int main()
{
my_auto_ptr<int> a(new int(2));
my_auto_ptr<int> b(new int(3));
a = b; // 這個賦值發生了什么? 其實這個賦值調用了重載的賦值運算符 b對象的指針已經被置為零
my_auto_ptr<int> c = a; // 這一步又發生了什么? a指針已經賦值給了c 同時 a指針置零了
std::cout << *c << std::endl; //輸出為3
// std::cout << *a << *b << std::endl; a和b的指針已經為零 此處報錯
return 0;
}
/*
智能指針保持了賦值和拷貝時將被拷貝的指針置零防止了內存泄漏發生
其實c++標准庫中已經實現了更加高階的智能指針,c++11之后此版本的智能指針已經棄之不用。
*/