当前位置: 首页 > news >正文

C++简单缓冲区类设计

目录

1.引言

2.静态缓冲区

3.动态缓冲区

4.数据引用类

5.自动数据引用类

6.几种缓冲区的类关系图

7.注意事项

8.完整代码


1.引言

        在C++中,设计静态和动态缓冲区类时,需要考虑的主要差异在于内存管理的方式。静态缓冲区类通常使用固定大小的内存区域(即栈分配或静态分配),而动态缓冲区类则根据需要动态地分配和释放内存(即堆分配)。下面将分别展示这几种缓冲区类的基本设计思路。

        不管是静态缓冲区还是动态缓冲区,都有统一的访问接口,于是提取共用方法,组成基础类:

template <class T>
class CSimpleDataBufferBase : public CNoncopyable
{
public:typedef T  DataType;typedef T* DataTypePointer;typedef T& DataTypeReference;typedef const T ConstDataType;typedef const T* ConstDataTypePointer;typedef const T& ConstDataTypeReference;public:CSimpleDataBufferBase() {}virtual ~CSimpleDataBufferBase() {}public:virtual  DWORD GetSize() const = 0;virtual  DataTypePointer GetData() = 0;virtual  ConstDataTypePointer GetData() const = 0;virtual  DWORD GetMaxSize() const = 0;operator DataTypePointer() {  return GetData(); } DataTypeReference operator*() { return *GetData(); }DataTypeReference operator[](int nIndex);virtual  BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize) = 0;virtual  void  Clear() = 0;
};

接口设计要点:

1)CSimpleDataBufferBase继承CNoncopyable,禁止构造拷贝和赋值拷贝。

2)访问缓冲区数据的接口,const和非const版本。

3)重载操作符*或[]访问缓冲区元素的数据

template <class T>
typename CSimpleDataBufferBase<T>::DataTypeReference CSimpleDataBufferBase<T>::operator[](int nIndex)
{if ( (nIndex >= 0) && (nIndex < (int)GetSize())){DataTypePointer pData = GetData();return pData[nIndex];}else{throw std::out_of_range("invalid data<nIndex> position");}	
}

4)往缓冲区写数据接口,接收的是const T*和数据的长度。

5)获取缓冲区的上限。

5)清空缓冲区。

2.静态缓冲区

        静态缓冲区类通常包含一个固定大小的数组(或其他容器,但数组是最直接的例子),并提供一系列方法来操作这个数组。 静态缓冲区类CStaticSimpleDataBufferT实现代码如下:

//数据静态分配
template <class T>
class CStaticSimpleDataBufferT : public CSimpleDataBufferBase<T>
{
public:CStaticSimpleDataBufferT(DWORD dwMaxSize = MAX_STATIC_SIMPLE_BUFFER_SIZE);virtual ~CStaticSimpleDataBufferT() {  }public:DWORD GetSize() const { return m_dwDataLen; }DataTypePointer GetData() { return m_sData ;}ConstDataTypePointer GetData() const { return m_sData ;}BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize);DWORD GetMaxSize() const {  return m_dwMaxDataSize; }void  Clear() { m_dwDataLen = 0; }private:DataType m_sData[MAX_STATIC_SIMPLE_BUFFER_SIZE];DWORD   m_dwDataLen;const DWORD m_dwMaxDataSize;		
};

        从实现的代码看,静态缓冲区就是在内存中事先分配好一段空间,这种分配一般是在栈中进行,分配速度特别快,但是不灵活,不能按照用户的大小需求分配空间。

3.动态缓冲区

        动态缓冲区类通常基于动态内存分配(如newdelete)来满足用户的需求。静态缓冲区的大小在编译时确定,而动态缓冲区的大小则根据需要动态变化。静态缓冲区适用于那些大小已知且不会改变的场景,而动态缓冲区则更灵活,适用于大小可能变化的场景。动态缓冲区类CDynamicSimpleDataBufferT实现代码如下:

//CSimpleDataBufferBase的默认适配器
template <class T>
class  CSimpleDataBufferAdapter : public CSimpleDataBufferBase<T>
{
public:CSimpleDataBufferAdapter() : m_pData(NULL),m_dwDataLen(0) { }virtual ~CSimpleDataBufferAdapter() { }public:DWORD GetSize() const { return m_dwDataLen; }BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize) {  assert(0); return FALSE; }void  SetSize(DWORD dwSize) { m_dwDataLen = dwSize; }DWORD GetMaxSize() const {  assert(0); return 0; }void  Clear() {  assert(0); }DataTypePointer GetData() { return m_pData ;}ConstDataTypePointer GetData() const { return m_pData ;}protected:DataTypePointer  m_pData;DWORD   m_dwDataLen;	
};/动态缓冲区
template <class T>
class  CDynamicSimpleDataBufferT : public CSimpleDataBufferAdapter<T>
{
public:CDynamicSimpleDataBufferT(DWORD dwMaxSize = MAX_DYNAMIC_SIMPLE_BUFFER_SIZE);virtual ~CDynamicSimpleDataBufferT() { ClearData(); }public:void  Clear() {  m_dwDataLen = 0; }DWORD GetMaxSize() const { return m_dwMaxDataSize; }BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize);protected:void  ClearData();private:const DWORD m_dwMaxDataSize;
};

构造函数、析构函数、赋值函数实现如下:

//构造函数
template <class T>
CDynamicSimpleDataBufferT<T>::CDynamicSimpleDataBufferT(DWORD dwMaxSize)
: m_dwMaxDataSize(dwMaxSize)
{m_pData = new T[dwMaxSize];if (m_pData == NULL)throw std::	bad_alloc("new T Array Failed");m_dwDataLen = 0;assert(m_pData != NULL);assert(m_dwDataLen >= 0);
}//清空数据函数
template <class T>
void  CDynamicSimpleDataBufferT<T>::ClearData()
{if (m_pData)delete []m_pData;m_pData = NULL;m_dwDataLen = 0;
}//赋值函数
template <class T>
BOOL CDynamicSimpleDataBufferT<T>::SetData(ConstDataTypePointer pData, DWORD dwSize)
{int  i;if (dwSize > m_dwMaxDataSize)return FALSE;for (i = 0; i < (int)dwSize; i++)m_pData[i] = pData[i];m_dwDataLen = dwSize;return TRUE;
}

        析构函数自动调用了Clear函数,释放了内存,这样就不怕退出的时候出现内存泄漏。

4.数据引用类

        在前面讲解的静态缓冲区和动态缓冲区内部都需要开辟空间,而数据引用类不需要开辟空间;CRefSimpleDataBufferT的具体实现如下:

template <class T>
class  CRefSimpleDataBufferT : public CSimpleDataBufferAdapter<T>
{
public:CRefSimpleDataBufferT() { }CRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize);virtual ~CRefSimpleDataBufferT()  {  }public:BOOL  SetData(ConstDataTypePointer pBuffer, DWORD dwSize);void  Clear();
};template <class T>
CRefSimpleDataBufferT<T>::CRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize)
{m_pData = const_cast<DataTypePointer>(pBuffer);m_dwDataLen = dwSize;
}template <class T>
void CRefSimpleDataBufferT<T>::Clear()
{if (m_pData)delete []m_pData;m_pData = NULL;m_dwDataLen = 0;
}template <class T>
BOOL  CRefSimpleDataBufferT<T>::SetData(typename CRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer, DWORD dwSize)
{Clear();m_pData = const_cast<DataTypePointer>(pBuffer);m_dwDataLen = dwSize;return TRUE;
}

从实现的代码来看,如果引用的数据是动态分配的,就可以调用Clear函数释放内存,反之,则不需要调用。

5.自动数据引用类

自动数据引用类就是引用外部的动态分配的数据源,并自动释放这个数据源的内存。CAutoRefSimpleDataBufferT的实现代码如下:

//自动释放动态分配的数据引用类
template <class T>
class  CAutoRefSimpleDataBufferT : public CRefSimpleDataBufferT<T>
{	
public:CAutoRefSimpleDataBufferT() { }CAutoRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize);CAutoRefSimpleDataBufferT(ConstDataTypePointer pBuffer);void  Clear();DataTypePointer   operator->() { return GetData(); }ConstDataTypePointer   operator->() const  { return GetData(); }virtual ~CAutoRefSimpleDataBufferT();
};template <class T>
CAutoRefSimpleDataBufferT<T>::CAutoRefSimpleDataBufferT(typename CAutoRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer, DWORD dwSize)
: CRefSimpleDataBufferT<T>(pBuffer, dwSize)
{
}template <class T>
CAutoRefSimpleDataBufferT<T>::CAutoRefSimpleDataBufferT(typename CAutoRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer)
: CRefSimpleDataBufferT<T>(pBuffer, 1)
{
}template <class T>
void CAutoRefSimpleDataBufferT<T>::Clear()
{if (1 == m_dwDataLen)delete m_pData;elseCRefSimpleDataBufferT<T>::Clear();
}template <class T>
CAutoRefSimpleDataBufferT<T>::~CAutoRefSimpleDataBufferT()
{Clear();
}

CAutoRefSimpleDataBufferT和CRefSimpleDataBufferT的不同点就在于析构函数自动调用了Clear函数,释放了数据源的内存。

6.几种缓冲区的类关系图

7.注意事项

1)静态成员变量的初始化:静态成员变量需要在类外进行初始化,并且只能初始化一次。

2)线程安全:如果多个线程可能同时访问这个静态缓冲区,你需要实现适当的同步机制来避免数据竞争和不一致。

3)资源管理:静态缓冲区在程序结束时自动销毁,但如果你在其中存储了动态分配的资源(如指针指向的堆内存),你需要确保在程序结束前正确释放这些资源。

4)性能考虑:静态缓冲区大小固定,如果缓冲区大小设置不当,可能会导致频繁的内存溢出或内存浪费。

5)并发访问:在并发环境中,如果多个线程可能同时写入或读取缓冲区,需要考虑使用互斥锁(如std::mutex)来同步访问。

8.完整代码

Noncopyable.h

/*************************************************************************// 功能: 防止拷贝类// 备注: *************************************************************************/
#pragma onceclass  CNoncopyable
{
public:CNoncopyable() {}~CNoncopyable() {}protected:CNoncopyable(const CNoncopyable& src);  //拷贝构造函数const CNoncopyable& operator=(const CNoncopyable& src); //赋值函数
};

SimpleDataBuffer.h

#pragma once
#include "Noncopyable.h"
#include <assert.h>
#include <new>
#include <stdexcept>
using namespace std;#define  MAX_STATIC_SIMPLE_BUFFER_SIZE  	  (4*1024)  //4K
#define  MAX_DYNAMIC_SIMPLE_BUFFER_SIZE       (800*1024) //800Ktemplate <class T>
class CSimpleDataBufferBase : public CNoncopyable
{
public:typedef T  DataType;typedef T* DataTypePointer;typedef T& DataTypeReference;typedef const T ConstDataType;typedef const T* ConstDataTypePointer;typedef const T& ConstDataTypeReference;public:CSimpleDataBufferBase() {}virtual ~CSimpleDataBufferBase() {}public:virtual  DWORD GetSize() const = 0;virtual  DataTypePointer GetData() = 0;virtual  ConstDataTypePointer GetData() const = 0;virtual  DWORD GetMaxSize() const = 0;operator DataTypePointer() {  return GetData(); } DataTypeReference operator*() { return *GetData(); }DataTypeReference operator[](int nIndex);virtual  BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize) = 0;virtual  void  SetSize(DWORD dwSize) = 0;virtual  void  Clear() = 0;
};template <class T>
typename CSimpleDataBufferBase<T>::DataTypeReference CSimpleDataBufferBase<T>::operator[](int nIndex)
{if ( (nIndex >= 0) && (nIndex < (int)GetSize())){DataTypePointer pData = GetData();return pData[nIndex];}else{throw std::out_of_range("invalid data<nIndex> position");}	
}//数据静态分配
template <class T>
class CStaticSimpleDataBufferT : public CSimpleDataBufferBase<T>
{
public:CStaticSimpleDataBufferT(DWORD dwMaxSize = MAX_STATIC_SIMPLE_BUFFER_SIZE);virtual ~CStaticSimpleDataBufferT() {  }public:DWORD GetSize() const { return m_dwDataLen; }DataTypePointer GetData() { return m_sData ;}ConstDataTypePointer GetData() const { return m_sData ;}BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize);void  SetSize(DWORD dwSize) { m_dwDataLen = dwSize; }DWORD GetMaxSize() const {  return m_dwMaxDataSize; }void  Clear() { m_dwDataLen = 0; }private:DataType m_sData[MAX_STATIC_SIMPLE_BUFFER_SIZE];DWORD   m_dwDataLen;const DWORD m_dwMaxDataSize;		
};template <class T>
CStaticSimpleDataBufferT<T>::CStaticSimpleDataBufferT(DWORD dwMaxSize)
:  m_dwDataLen(0),m_dwMaxDataSize(dwMaxSize)
{
}template <class T>
BOOL  CStaticSimpleDataBufferT<T>::SetData(ConstDataTypePointer pData, DWORD dwSize)
{int  i;if (dwSize > m_dwMaxDataSize)return FALSE;for (i = 0; i < (int)dwSize; i++)m_sData[i] = pData[i];m_dwDataLen = dwSize;return TRUE;
}
///
template <class T>
class  CSimpleDataBufferAdapter : public CSimpleDataBufferBase<T>
{
public:CSimpleDataBufferAdapter() : m_pData(NULL),m_dwDataLen(0) { }virtual ~CSimpleDataBufferAdapter() { }public:DWORD GetSize() const { return m_dwDataLen; }BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize) {  assert(0); return FALSE; }void  SetSize(DWORD dwSize) { m_dwDataLen = dwSize; }DWORD GetMaxSize() const {  assert(0); return 0; }void  Clear() {  assert(0); }DataTypePointer GetData() { return m_pData ;}ConstDataTypePointer GetData() const { return m_pData ;}protected:DataTypePointer  m_pData;DWORD   m_dwDataLen;	
};/
template <class T>
class  CDynamicSimpleDataBufferT : public CSimpleDataBufferAdapter<T>
{
public:CDynamicSimpleDataBufferT(DWORD dwMaxSize = MAX_DYNAMIC_SIMPLE_BUFFER_SIZE);virtual ~CDynamicSimpleDataBufferT() { ClearData(); }public:void  Clear() {  m_dwDataLen = 0; }DWORD GetMaxSize() const { return m_dwMaxDataSize; }BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize);protected:void  ClearData();private:const DWORD m_dwMaxDataSize;
};template <class T>
CDynamicSimpleDataBufferT<T>::CDynamicSimpleDataBufferT(DWORD dwMaxSize)
: m_dwMaxDataSize(dwMaxSize)
{m_pData = new T[dwMaxSize];if (m_pData == NULL)throw std::	bad_alloc("new T Array Failed");m_dwDataLen = 0;assert(m_pData != NULL);assert(m_dwDataLen >= 0);
}template <class T>
void  CDynamicSimpleDataBufferT<T>::ClearData()
{if (m_pData)delete []m_pData;m_pData = NULL;m_dwDataLen = 0;
}template <class T>
BOOL CDynamicSimpleDataBufferT<T>::SetData(ConstDataTypePointer pData, DWORD dwSize)
{int  i;if (dwSize > m_dwMaxDataSize)return FALSE;for (i = 0; i < (int)dwSize; i++)m_pData[i] = pData[i];m_dwDataLen = dwSize;return TRUE;
}
//
template <class T>
class  CRefSimpleDataBufferT : public CSimpleDataBufferAdapter<T>
{
public:CRefSimpleDataBufferT() { }CRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize);virtual ~CRefSimpleDataBufferT()  {  }public:BOOL  SetData(ConstDataTypePointer pBuffer, DWORD dwSize);void  Clear();
};template <class T>
CRefSimpleDataBufferT<T>::CRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize)
{m_pData = const_cast<DataTypePointer>(pBuffer);m_dwDataLen = dwSize;
}template <class T>
void CRefSimpleDataBufferT<T>::Clear()
{if (m_pData)delete []m_pData;m_pData = NULL;m_dwDataLen = 0;
}template <class T>
BOOL  CRefSimpleDataBufferT<T>::SetData(typename CRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer, DWORD dwSize)
{Clear();m_pData = const_cast<DataTypePointer>(pBuffer);m_dwDataLen = dwSize;return TRUE;
}//自动释放动态分配的数据引用类
template <class T>
class  CAutoRefSimpleDataBufferT : public CRefSimpleDataBufferT<T>
{	
public:CAutoRefSimpleDataBufferT() { }CAutoRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize);CAutoRefSimpleDataBufferT(ConstDataTypePointer pBuffer);void  Clear();DataTypePointer   operator->() { return GetData(); }ConstDataTypePointer   operator->() const  { return GetData(); }virtual ~CAutoRefSimpleDataBufferT();
};template <class T>
CAutoRefSimpleDataBufferT<T>::CAutoRefSimpleDataBufferT(typename CAutoRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer, DWORD dwSize)
: CRefSimpleDataBufferT<T>(pBuffer, dwSize)
{
}template <class T>
CAutoRefSimpleDataBufferT<T>::CAutoRefSimpleDataBufferT(typename CAutoRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer)
: CRefSimpleDataBufferT<T>(pBuffer, 1)
{
}template <class T>
void CAutoRefSimpleDataBufferT<T>::Clear()
{if (1 == m_dwDataLen)delete m_pData;elseCRefSimpleDataBufferT<T>::Clear();
}template <class T>
CAutoRefSimpleDataBufferT<T>::~CAutoRefSimpleDataBufferT()
{Clear();
}
http://www.lryc.cn/news/447577.html

相关文章:

  • MySQL 数据库
  • 基于单片机的智能校园照明系统
  • 高性能分布式搜索引擎Elasticsearch详解
  • 连锁收银系统的五大功能 选择开源收银系统三要素
  • 虚幻引擎解决构建问题
  • C++基础知识:C++中读文件的四种简单方式
  • 【人工智能】多模态AI:如何通过融合文本、图像与音频重塑智能系统未来
  • 通过重写QStyle控制QT控件样式
  • WPF入门教学十八 动画入门
  • 电信光猫破解记录
  • 鸿蒙界面开发(九):列表布局 (List)
  • 微服务远程调用(nacos及OpenFeign简单使用)
  • Protobuf vs Thrift: 高性能序列化框架的对比与分析
  • LeetCode Hot100 C++ 哈希 1.两数之和
  • Windows下安装Neo4j流程
  • Spring IDEA 2024 自动生成get和set以及toString方法
  • 部署my2sql
  • Android Studio 真机USB调试运行频繁掉线问题
  • 如何通过费曼技巧理解复杂主题
  • Golang优雅关闭gRPC实践
  • Maven笔记(一):基础使用【记录】
  • [vulnhub] Jarbas-Jenkins
  • js设计模式(26)
  • 数据库中, drop、delete与truncate的区别?
  • 2024年项目经理不能错过的开源项目管理系统大盘点:全面指南
  • MATLAB基本语句
  • 委托的注册及注销+观察者模式
  • Jetpack02-LiveData 数据驱动UI更新(类似EventBus)
  • Redis 的 Java 客户端有哪些?官方推荐哪个?
  • 工作笔记20240927——vscode + jlink调试