【十九】一些实际工程中的问题

1、Bug

  • 在实际工程中内存操作是bug的重要来源
  • C++将堆内存交由开发人员自由使用,因此
    • 未及时释放,将产生内存泄漏
    • 重复释放同一段内存,行为未知
    • 使用越界,操作了不属于自己的内存

思考:
怎样最大限度的避开上述的使用问题?

2、数组类
内存越界的问题常发生于数组的使用中
解决方案:数组类

工程中,在非特殊情况下,要求开发者使用预先编写的数组类对象代替C++语言中的原生数组,而其实C++中也已经提供了这样的数组类!

数组类的自定义实现:

array.h

#ifndef _ARRAY_H_
#define _ARRAY_H_

template <typename T>
class Array
{
private:
  int     m_length;
  T*      m_pointer;

public:
  Array();
  Array(int length);
  Array(const Array<T>& obj);
  ~Array();

  int Length();
  T& operator[] (int i);
  Array<T>& operator= (const Array<T>& obj);
  bool operator== (const Array<T>& obj);
  bool operator!= (const Array<T>& obj);
};

#endif

array.hpp

#ifndef _ARRAY_DEF_H_
#define _ARRAY_DEF_H_

#include "array.h"


/*
* 构造函数
* 参  数:
*     无
* 返回值:
*     无
*/
template <typename T>
Array<T>::Array() : m_length(0),m_pointer(nullptr)
{

}


/*
* 构造函数
* 参  数:
*     数组长度,应该大于等于0的整数
* 返回值:
*     无
*/
template <typename T>
Array<T>::Array(int length) : m_length(0),m_pointer(nullptr)
{
  if(length < 0)
  {
    length = 0;
  }
  m_length = length;
  m_pointer = new T[m_length];
}


/*
* 拷贝构造函数
* 参  数:
*     被拷贝的对象引用
* 返回值:
*     无
*/
template <typename T>
Array<T>::Array(const Array<T>& obj): m_length(0),m_pointer(nullptr)
{
  m_length = obj.m_length;
  m_pointer = new T[m_length];
  if(m_pointer != nullptr)
  {
    for(int i = 0; i < m_length; i++)
    {
      m_pointer[i] = obj.m_pointer[i];
    }
  }
}


/*
* 析构函数
* 参  数:
*     无
* 返回值:
*     无
*/
template <typename T>
Array<T>::~Array()
{
  m_length = 0;
  if(m_pointer != nullptr)
  {
    delete[] m_pointer;
    m_pointer = nullptr;
  }
}

/*
* 获取数组长度
* 参  数:
*     无
* 返回值:
*     返回数组长度,应该是一个非负值
*/
template <typename T>
int Array<T>::Length()
{
  return m_length;
}


/*
* 重载数组下标运算符,访问数组元素
* 参  数:
*     要访问的元素的下标
* 返回值:
*     返回该下标元素的引用
*/
template <typename T>
T& Array<T>::operator[] (int i)
{
  if(( 0 <= i ) && (i < m_length))
  {
    return m_pointer[i];
  }
  else
  {
    return m_pointer[0];
  }
}


/*
* 拷贝数组类
* 参  数:
*     被拷贝的数组对象的引用
* 返回值:
*     返回新对象的引用
*/
template <typename T>
Array<T>& Array<T>::operator= (const Array<T>& obj)
{
  if(m_pointer != nullptr)
  {
    delete[] m_pointer;
    m_pointer = nullptr;
  }
  m_length = obj.m_length;
  m_pointer = new T[m_length];
  if(m_pointer != nullptr)
  {
    for(int i = 0; i < m_length; i++)
    {
      m_pointer[i] = obj.m_pointer[i];
    }
  }
  return *this;
}


/*
* 判断两个数组是否相等
* 参  数:
*     数组对象的引用
* 返回值:
*     相等,返回true;不相等,返回false
*/
template <typename T>
bool Array<T>::operator== (const Array<T>& obj)
{
  bool ret = true;
  if(m_length == obj.m_length)
  {
    for(int i = 0; i < m_length; i++)
    {
      if(m_pointer[i] != obj.m_pointer[i])
      {
        ret = false;
        break;
      }
    }
  }
  else
  {
    ret = false;
  }
  return ret;
}

/*
* 判断两个数组是否不等
* 参  数:
*     数组对象的引用
* 返回值:
*     相等,返回false;不相等,返回true
*/
template <typename T>
bool Array<T>::operator!= (const Array<T>& obj)
{
  return !(*this == obj);
}


#endif

main.cpp

#include <iostream>
#include "array.hpp"
using namespace std;


int main()
{
  Array<double> ab(5);
  for(int i = 0; i < ab.Length(); i++)
  {
    ab[i] = i * 0.1 + 0.1;
    cout << "ab["<< i << "] = " << ab[i] << '\t';
  }
  cout << endl;

  Array<double> ac(5);
  for(int i = 0; i < ac.Length(); i++)
  {
    ac[i] = i * 0.1 + 0.1;
    cout << "ac["<< i << "] = " << ac[i] << '\t';
  }
  cout << endl;

  Array<double> ad = ac;    //拷贝构造函数

  if(ad != ac)
  {
    cout << "ad != ac" << endl;
  }
  else
  {
    cout << "ad == ac" << endl;
  }
  for(int i = 0; i < ad.Length(); i++)
  {
    ad[i] = i + 1;
    cout << "ad["<< i << "] = " << ad[i] << '\t';
  }
  cout << endl;

  Array<double> ae;
  ae = ad;    //拷贝对象

  for(int i = 0; i < ae.Length(); i++)
  {
    ae[i] = i + 1;
    cout << "ae["<< i << "] = " << ae[i] << '\t';
  }
  cout << endl;

  return 0;
}

以上代码,仅仅是对C++内置数组类实现的一个模拟和猜想!

3、智能指针

内存泄漏和内存多次释放常发生于指针的使用过程中

解决方案:智能指针

工程中,要求开发者使用预先编写的智能指针类对象代替C语言中的原生指针!

什么是智能指针?

工程中的智能指针是一个类模板

  • 通过构造函数接管申请的堆内存
  • 通过析构函数确保堆内存被及时释放
  • 通过重载指针运算符* 和->模拟指针的行为
  • 通过重载比较运算符== 和 != 模拟指针的比较

以下智能指针类结合了引用计数机制进行内存的释放!

smartpointer.h

#ifndef _SMARTPOINTER_H_
#define _SMARTPOINTER_H_

template <typename T>
class SmartPointer
{
private:
  int*  m_refcount;
  T*    m_pointer;

public:
  SmartPointer();
  SmartPointer(const T* pointer);
  SmartPointer(const SmartPointer<T>& obj);
  ~SmartPointer();
  T& operator* ();
  T* operator-> ();
  SmartPointer<T>& operator= (const SmartPointer<T>& obj);
  bool operator== (const SmartPointer<T>& obj);
  bool operator!= (const SmartPointer<T>& obj);

  int GetrefCount();
private:
  void IncrefCount();
  void DecrefCount();
};


#endif

smartpoint.hpp

#ifndef _SMARTPOINTER_DEF_H_
#define _SMARTPOINTER_DEF_H_
#include <iostream>
using namespace std;
#include "smartpointer.h"

/*
* 获取当前对象引用计数数值
* 参  数:
      无
* 返回值:
      如果成功,返回非负数,失败返回-1
*/
template <typename T>
int SmartPointer<T>::GetrefCount()
{
  if(m_refcount != nullptr)
  {
    return *m_refcount;
  }
  else
  {
    return -1;
  }
}


/*
* 增加当前对象引用计数数值,+1
* 参  数:
      无
* 返回值:
      无
*/
template <typename T>
void SmartPointer<T>::IncrefCount()
{
  if(m_refcount != nullptr)
  {
    ++(*m_refcount);
  }
}


/*
* 减小当前对象引用计数数值,-1
* 参  数:
      无
* 返回值:
      无
*/
template <typename T>
void SmartPointer<T>::DecrefCount()
{
  if(m_refcount != nullptr)
  {
    --(*m_refcount);
  }
}

/*
* 构造函数
* 参  数:
      无
* 返回值:
      无
*/
template <typename T>
SmartPointer<T>::SmartPointer() : m_refcount(nullptr), m_pointer(nullptr)
{

}

/*
* 构造函数
* 参  数:
      指向的堆地址
* 返回值:
      无
*/
template <typename T>
SmartPointer<T>::SmartPointer(const T* pointer) : m_refcount(nullptr), m_pointer(nullptr)
{
  m_pointer = const_cast<T*>(pointer);
  if(m_pointer != nullptr)
  {
    if(m_refcount == nullptr)
    {
      m_refcount = new int(1);
    }
  }
}

/*
* 拷贝构造函数
* 参  数:
      一个SmartPointer<T>对象的引用
* 返回值:
      无
*/
template <typename T>
SmartPointer<T>::SmartPointer(const SmartPointer<T>& obj): m_refcount(nullptr), m_pointer(nullptr)
{
  m_pointer = obj.m_pointer;
  m_refcount = obj.m_refcount;
  IncrefCount();
}


/*
* 析构函数
* 参  数:
      无
* 返回值:
      无
*/
template <typename T>
SmartPointer<T>::~SmartPointer()
{
  if(m_pointer != nullptr)
  {
    DecrefCount();
    if(GetrefCount() <= 0)
    {
      delete m_pointer;
      m_pointer = nullptr;
      delete m_refcount;
      m_refcount = nullptr;
    }
  }
}


/*
* 重载解引用操作符
* 参  数:
      无
* 返回值:
      该对象所指地址空间对象的引用
*/
template <typename T>
T& SmartPointer<T>::operator* ()
{
  return *m_pointer;
}


/*
* 重载指针成员操作符
* 参  数:
      无
* 返回值:
      该对象所指地址空间指针
*/
template <typename T>
T* SmartPointer<T>::operator-> ()
{
  return m_pointer;
}

/*
* 重载赋值运算符
* 参  数:
      一个SmartPointer<T>对象的引用
* 返回值:
      该对象本身的引用
*/
template <typename T>
SmartPointer<T>& SmartPointer<T>::operator= (const SmartPointer<T>& obj)
{
  this->~SmartPointer();

  m_pointer = obj.m_pointer;
  m_refcount = obj.m_refcount;
  IncrefCount();
  return *this;
}


/*
* 重载比较运算符==
* 参  数:
      一个SmartPointer<T>对象的引用
* 返回值:
      如果相等,返回true;不等,返回false;
*/
template <typename T>
bool SmartPointer<T>::operator== (const SmartPointer<T>& obj)
{
  if(m_pointer == obj.m_pointer)
  {
    return true;
  }
  else
  {
    return false;
  }
}


/*
* 重载比较运算符!=
* 参  数:
      一个SmartPointer<T>对象的引用
* 返回值:
      如果不相等,返回true;相等,返回false;
*/
template <typename T>
bool SmartPointer<T>::operator!= (const SmartPointer<T>& obj)
{
  return !(*this == obj);
}


#endif

main.cpp

#include <iostream>
#include "smartpointer.hpp"

using namespace std;

class Student
{
public:
  const char*   Name;
  int     Age;

public:
  Student(const char* str, int age)
  {
    Name = str;
    Age = age;
  }
};

void func()
{
  SmartPointer<int> pi = new int(5);
  cout << "pi.refcount = "<< pi.GetrefCount() << endl;

  SmartPointer<int> pii;
  pii = pi;
  cout << "pi.refcount = "<< pi.GetrefCount() << endl;

  SmartPointer<int> pt = new int(100);
  cout <<"pt.refcount = "<< pt.GetrefCount() << endl;

  pi = pt;
  cout << "pii.refcount = "<< pii.GetrefCount() << endl;
  cout <<"pt.refcount = "<< pt.GetrefCount() << endl;

  if(pi == pii)
  {
    cout << "pi == pii" << endl;
  }
  else
  {
    cout << "pi != pii" << endl;
  }

  SmartPointer<Student> stu = new Student("Tom",20);
  cout << "Name = " << stu->Name << '\t' << "Age = " << stu->Age << endl;
}

int main()
{
  func();
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值