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;
}