一、什么是智能指针
由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete。程序员忘记 delete,流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 delete 的情况并不罕见。用智能指针便可以有效缓解这类问题
引用《more effective c++》中的话:
所谓的智能指针,是看起来,用起来感觉都像是内建的指针,但提供更多功能的一种对象。
因此说:
智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针。智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放。
二、常见的智能指针
1. std::auto_ptr
有很多问题。 不支持复制(拷贝构造函数)和赋值(operator =),但复制或赋值的时候不会提示出错,因为不能被复制,所以不能被放入容器中。
2. unique_ptr
也不支持复制和赋值,但比auto_ptr好,直接赋值会编译出错。实在想赋值的话,需要使用:std::move。
std::unique_ptr p1(new int(5));
std::unique_ptr p2 = p1; // 编译会出错
std::unique_ptr p3 = std::move(p1); // 转移所有权, 现在那块内存归p3所有, p1成为无效的指针.
3. shared_ptr
基于引用计数的智能指针。可随意赋值,直到内存的引用计数为0的时候这个内存会被释放。
三、智能指针的实现与比较
下面是一个基于引用计数的智能指针的实现,需要实现构造,析构,拷贝构造,=操作符重载,重载*-和>操作符。
#include<iostream>
#include<memory>
using namespace std;
template <typename T>
class SmartPointer {
public:
//构造函数
SmartPointer(T* p = 0) : _ptr(p), _reference_count(new size_t) {
if (p)
*_reference_count = 1;
else
*_reference_count = 0;
}
//拷贝构造函数
SmartPointer(const SmartPointer& src) {
if (this != &src) {
_ptr = src._ptr;
_reference_count = src._reference_count;
(*_reference_count)++;
}
}
//重载赋值操作符
SmartPointer& operator=(const SmartPointer& src) {
if (_ptr == src._ptr) {
return *this;
}
releaseCount();
_ptr = src._ptr;
_reference_count = src._reference_count;
(*_reference_count)++;
return *this;
}
//重载操作符
T& operator*() {
if (_ptr) {
return *_ptr;
}
//throw exception
}
//重载操作符
T* operator->() {
if (_ptr) {
return _ptr;
}
//throw exception
}
//析构函数
~SmartPointer() {
if (--(*_reference_count) == 0) {
delete _ptr;
delete _reference_count;
}
}
private:
T *_ptr;
size_t *_reference_count;
void releaseCount() {
if (_ptr) {
(*_reference_count)--;
if ((*_reference_count) == 0) {
delete _ptr;
delete _reference_count;
}
}
}
};
建立一个对象用于检测:
class Simple {
public:
Simple(int param = 0) {
number = param;
std::cout << "Simple: " << number << std::endl;
}
~Simple() {
std::cout << "~Simple: " << number << std::endl;
}
int number;
};
完整的运行测试代码:
#include<iostream>
#include<memory>
using namespace std;
template <typename T>
class SmartPointer {
public:
//构造函数
SmartPointer(T* p = 0) : _ptr(p), _reference_count(new size_t) {
if (p)
*_reference_count = 1;
else
*_reference_count = 0;
}
//拷贝构造函数
SmartPointer(const SmartPointer& src) {
if (this != &src) {
_ptr = src._ptr;
_reference_count = src._reference_count;
(*_reference_count)++;
}
}
//重载赋值操作符
SmartPointer& operator=(const SmartPointer& src) {
if (_ptr == src._ptr) {
return *this;
}
releaseCount();
_ptr = src._ptr;
_reference_count = src._reference_count;
(*_reference_count)++;
return *this;
}
//重载操作符
T& operator*() {
if (_ptr) {
return *_ptr;
}
//throw exception
}
//重载操作符
T* operator->() {
if (_ptr) {
return _ptr;
}
//throw exception
}
//析构函数
~SmartPointer() {
if (--(*_reference_count) == 0) {
delete _ptr;
delete _reference_count;
}
}
private:
T *_ptr;
size_t *_reference_count;
void releaseCount() {
if (_ptr) {
(*_reference_count)--;
if ((*_reference_count) == 0) {
delete _ptr;
delete _reference_count;
}
}
}
};
class Simple {
public:
Simple(int param = 0) {
number = param;
std::cout << "Simple: " << number << std::endl;
}
~Simple() {
std::cout << "~Simple: " << number << std::endl;
}
int number;
};
int main()
{
SmartPointer<char> cp1(new char('a'));
cout << *cp1 << endl;
SmartPointer<char> cp2(cp1);
cout << *cp2 << endl;
SmartPointer<char> cp3;
cp3 = cp2;
cp3 = cp1;
cp3 = cp3;
SmartPointer<char> cp4(new char('b'));
cp3 = cp4;
cout << *cp3 << endl;
//
auto_ptr<Simple> autoPtr(new Simple(10));
auto_ptr<Simple> autoPtr1;
cout << autoPtr->number << endl;
autoPtr1 = autoPtr;
cout << autoPtr1->number << endl;
cout << autoPtr->number << endl;
SmartPointer<Simple>myPointer(new Simple(1));
SmartPointer<Simple>myPointer1;
myPointer1 = myPointer;
cout<<myPointer1->number<<endl;
cout << myPointer->number << endl;
}
参考文章:
《more effective c++》
http://blog.csdn.net/xt_xiaotian/article/details/5714477
http://blog.csdn.net/worldwindjp/article/details/18843087