C++实现智能指针(一)

参考自《C5-C++ Primer》和实验楼相关实验。

一. 智能指针概念

  • 智能指针的引入:

C++中,通过new/delete这对运算符进行动态内存的管理。动态内存使用很容易出问题,因为确保在正确时间释放内存是很困难的。有时忘记释放内存,产生内存泄漏;有时在指针还引用内存时就释放了它,产生引用非法内存的指针。因此,为了更容易和安全地使用动态内存,C++11提供了智能指针(smart pointer)类型来管理动态对象。

  • 智能指针的使用:
所谓的智能指针,首先它是一个指针,所以能指向内存资源;然后它区别于一般的指针,它是智能的,而所谓的智能是指它:1.能够自动的帮你释放内存,2.还能够知道什么时候释放内存才是安全的。

标准提供两种智能指针:shared_ptr允许多个指针指向同一个对象;unique_ptr独占所指对象;weak_ptr指向shared_ptr所管理的对象。本实验主要实现shared_ptr的功能。

  • 智能指针的实现原理:
C++中智能指针的实现主要依赖于两个技术概念:
1. 析构函数,对象被销毁时会被调用的一个函数,对于基于栈的对象而言,如果对象离开其作用域则对象会被自动销毁,而此时析构函数也自动会被调用。

2. 引用计数技术,维护一个计数器用于追踪资源(如内存)的被引用数,当资源被引用时,计数器值加1,当资源被解引用时,计算器值减1。

智能指针的大致实现原理就是在析构函数中,检查所引用对象的引用计数,如果引用计数为0,则真正释放该对象内存。

二. 实现版本v1

  • 定义智能指针类
  • 创建构造函数:具备默认构造函数;指定类型构造函数
  • 定义为模板类
  • 析构函数:释放内存
实现智能指针:头文件 smartpointer.h
/* 
* file name : smartpointer.h
* desp : 智能指针版本v1
*/
#ifndef __SMARTPOINTER_H__
#define __SMARTPOINTER_H__

template <typename T>  // 将智能指针类定义成模板类
class SmartPointer {
public:
    // 默认构造函数
    SmartPointer():mPointer(NULL) {std::cout <<"create unknown smart pointer."<< std::endl;}    
    // 接收不同指针类型的构造函数
    SmartPointer(T *p):mPointer(p) {std::cout <<"create smart pointer at "<<static_cast<const void*>(p)<<std::endl;}     
    // 析构函数
    ~SmartPointer(){
        std::cout << "release smart pointer at "<<static_cast<const void*>(mPointer)<<std::endl;
        // 实现内存资源自动销毁机制
        if (mPointer) delete mPointer;
    }
private:
    T *mPointer; // 指向智能指针实际对应的内存资源,根据参数自动推导规则,定义内部资源指针类型
};
#endif // __SMARTPOINTER_H__

测试智能指针:测试文件 sptestcase1.cpp

/* 
* file name : sptestcase1.cpp
* desp : 智能指针测试代码 case1 测试智能指针的创建与销毁
*/

#include <iostream>
#include "smartpointer.h"
class SomeClass{
public:
    SomeClass(){std::cout << "SomeClass default constructor !"<<std::endl;}
};

void testcase1()
{
    // 创建一个不知所指的智能指针
    SmartPointer<char> spunknown;
    // 创建空智能指针
    SmartPointer<char> spnull = NULL;
    // 创建指向具体类的智能指针
    SmartPointer<SomeClass> spclass = new SomeClass;
    // 创建字符串的智能指针
    SmartPointer<const char> spstr = "Hello world!";  
}

int main(void)
{
    testcase1();
    return 0;
}

编译执行:

$ g++ -o sptestcase1 sptestcase1.cpp
$ ./sptestcase1

运行结果分析:


  • V1版本不足

简单实现智能指针类,智能指针释放指向“hello world”指针时出错。我们的智能指针不能指向无法被delete释放的内存资源。

三. 知识点查漏补缺

  • new的不同用法
(1)int *p=new int;//无初始化
(2)int *p=new int(5);//初始化为5
(3)创建类  Test *test=new Test();  delete test;//加括号调用没有参数的构造函数,不加括号调用默认构造函数或唯一的构造函数
(4)int *p=new int[10];//开辟容量为10的数组  delete []p;
  • 类模板
//类的定义
template<class T>
class Test
{
private:
    T n;
    const T i;
public:
    Test():i(0) {}
    Test(T k);
    ~Test(){}

    void print();
    T operator+(T x);
};
//类的使用
类名<实际的类型> eg.Test<int> test;//声明一个对象 
  • staic_cast<const void *>(p)

//地址?转换类型? 

我们这里定义的是模版类,因为不知道这个指针的具体类型。使用使用了const void *。

 const void * p 这是定义了一个指针p,p可以指向任意类型的值,但它指向的值必须是常量。在这种情况下,我们不能修改被指向的对象,但可以使指针指向其他对象。

猜你喜欢

转载自blog.csdn.net/qq_32274259/article/details/80191055