pppploi8's Blog

欢迎来到pppploi8的个人博客!

C++ Primer学习笔记-简单实现智能指针

在学完复制控制后本来就想写了,但是哪里还没讲模板,于是就拖到了现在

这只是按照书上的思路实现的非常简单的基于引用计数的智能指针,实际使用还是应该用标准库提供的

另外因为懒所以干脆把代码全丢到头文件了…恩,就是懒,没别的原因

最后…这个没实际用过..有BUG欢迎指出….至于线程安全就算了吧Orz…毕竟只是练手产物,实际要用还是标准库里的比较好吧…各种意义上

=====
HasPtr.h
=====

#ifndef HASPTR_H
#define HASPTR_H
/**
 * 这个类负责记录指针引用次数
 * 因为每次修改所有引用都应该更新 
 * 所以单独使用对象记录
 * 让多个指针对象指向一个记录对象即可 
**/
struct U_Ptr {
    int use;
    U_Ptr():use(1){  }
};
/**
 * 指针包装类
 * 负责保存指针地址
 * 并在无引用时自动删除指针指向对象
**/
template<class T> class HasPtr {
public:
    //构造函数
    HasPtr():ip(0),u(0){ }
    HasPtr(T* ptr):ip(ptr),u(new U_Ptr()){ }
    //定义复制构造函数和重载赋值运算符,来记录每次指针对象被复制后使用自增1
    HasPtr(const HasPtr& copy){
        ip = copy.ip;
        u = copy.u;
        ++u->use;
    }
    HasPtr& operator = (const HasPtr& copy) {
        ip = copy.ip;
        u = copy.u;
        ++u->use;
       return *this;
   }
    //重载->,*运算符,提供get()方法,来调用指针原来内容
    T* operator -> () {
        return ip;
    }
    T operator * () {
        return *ip;
    }
    T* get() {
        return ip;
    }
    //析构函数,递减使用数,如果使用数为0则删除指针
   ~HasPtr() {
       if (u!=0){
           if (--u->use <= 0){
               delete ip;
               delete u;
           }
       }
   }
private:
    T* ip;//记录指针变量
    U_Ptr* u;//记录引用次数对象
};
#endif 

=====
main.cpp
=====

#include <iostream>
#include <vector>
#include "HasPtr.h"

using namespace std;

class ObjectA {
public:
    ObjectA(int i):tmp(i) {
        cout << "对象("<< i << ")初始化" <<endl;
    }
    ~ObjectA(){
        cout << "对象("<< tmp <<")被清理" << endl;
    }
    void print () {
        cout << "对象("<< tmp <<")打印文字" << endl;
    }
private:
    int tmp;
};
vector<HasPtr<ObjectA> > getObjectAs(){
    vector<HasPtr<ObjectA> > lists;
    for(int i=0;i!=10;++i){
        HasPtr<ObjectA> t(new ObjectA(i));
        HasPtr<ObjectA> b;
        b = t;
        lists.push_back(b);
    }
    return lists;
}
int main() {
    vector<HasPtr<ObjectA> > lists = getObjectAs();
    for (int i=0;i!=lists.size();++i){
        lists[i]->print();
    }
    return 0;
}