智能指针的简单实现
在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之后此版本的智能指针已经弃之不用。
*/