_Array类,类似于Vector,其实就是_string

例子:

using namespace lf;
using namespace std;int main() {_Array<int> a(10, -1);_Array<_string> s = { _t("one"), _t("two") };_pcn(a);_pcn(s);}

结果:

源代码_Array.h:

/*******************************************************************************************
文件名						: _Array.h作者							: 李锋功能							: 线性表创建时间						: 2016年07月16日最后一次修改时间				:  2024年09月15日
********************************************************************************************/
#ifndef __ARRAY_H_  
#define __ARRAY_H_#include "_StrW.h"
#include "_StrA.h"
#include "_Convert.h"
#include "_Object.h"_LF_BEGIN_/**********************************************************************************************************
1
vector与list区别
vector为存储的对象分配一块连续的地址空间,因此对vector中的元素随机访问效率很高。在vecotor中插入或者
删除某个元素,需要将现有元素进行复制,移动。如果vector中存储的对象很大,或者构造函数复杂,则在对现
有元素进行拷贝时开销较大,因为拷贝对象要调用拷贝构造函数。对于简单的小对象,vector的效率优于list。
vector在每次扩张容量的时候,将容量扩展2倍,这样对于小对象来说,效率是很高的。list中的对象是离散存储的,
随机访问某个元素需要遍历list。在list中插入元素,尤其是在首尾插入元素,效率很高,只需要改变元素的指针。综上所述:
vector适用:对象数量变化少,简单对象,随机访问元素频繁
list适用:对象数量变化大,对象复杂,插入和删除频繁
最大的区别是, list是双向的,而vector是单向的。
因此在实际使用时,如何选择这三个容器中哪一个,应根据你的需要而定,一般应遵循下面
的原则:
1、如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector
2、如果你需要大量的插入和删除,而不关心随即存取,则应使用list
3、如果你需要随即存取,而且关心两端数据的插入和删除,则应使用deque。vector表示一段连续的内存区域,每个元素被顺序存储在这段内存中,对vector   的随机访问效率很高,但对非末尾元素的插入和删除则效率非常低。deque也表示一段连续的内存区域,但与vector不同的是它支持高效地在其首部插入和删除元素,它通过两级数组结构来实现,一级表示实际的容器,第二级指向容器的首和尾list表示非连续的内存区域并通过一对指向首尾元素的指针双向链接起来,插入删除效率高,随机访问效率低2stl提供了三个最基本的容器:vector, list, deque。vector和built - in数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此
它能非常好的支持随即存取,即[]操作符,但由于它的内存空间是连续的,所以在中间
进行插入和删除会造成内存块的拷贝,另外,当该数组后的内存空间不够时,需要重新
申请一块足够大的内存并进行内存的拷贝。这些都大大影响了vector的效率。list就是数据结构中的双向链表(根据sgi   stl源代码),因此它的内存空间可以是不连续
的,通过指针来进行数据的访问,这个特点使得它的随即存取变的非常没有效率,因此它
没有提供[]操作符的重载。但由于链表的特点,它可以以很好的效率支持任意地方的删除
和插入。deque是一个double - ended   queue,它的具体实现不太清楚,但知道它具有以下两个
特点:它支持[]操作符,也就是支持随即存取,并且和vector的效率相差无几,它支持在两端
的操作:push_back, push_front, pop_back, pop_front等,并且在两端操作上与list的效率
也差不多。因此在实际使用时,如何选择这三个容器中哪一个,应根据你的需要而定,一般应遵循下面
的原则:
1、如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector
2、如果你需要大量的插入和删除,而不关心随即存取,则应使用list
3、如果你需要随即存取,而且关心两端数据的插入和删除,则应使用deque。**********************************************************************************************************线性表的定义:一个线性表是n(n>=0)个具有相同属性的数据元素的有限序列。其中各元系有着依次相邻的逻辑关系。线性表中数据元素个数n称为线性表的长度。n=0时该线性表称为空表。**************************************************************************************************************/
//#define _ARRAY_DEBUG_/// <summary>
/// 
/// </summary>
/// <typeparam name="T"></typeparam>
template<class T>
class _ArrayIterator
{
private:T* _Ptr;
public:/// <summary>/// 构造函数,传值迭代器管理的值/// </summary>/// <param name="pNode"></param>inline _ArrayIterator(T* pt) { _Ptr = pt; }/// <summary>/// 比较实现/// </summary>/// <param name="that"></param>/// <returns></returns>bool operator != (const _ArrayIterator& that) { return _Ptr != that._Ptr; }/// <summary>/// 自增实现/// </summary>/// <returns></returns>inline _ArrayIterator& operator ++ () { ++_Ptr;   return *this; }/// <summary>/// 解引用,取值/// </summary>/// <typeparam name="T"></typeparam>T& operator * () { return *_Ptr; }};//_Array相当于std::vector,不限于线性表。
template<typename T>
class _Array : public _Object
{
public:
/*using traits_type    = _Traits;using allocator_type = _Alloc;using value_type      = _Elem;using size_type       = typename _Alty_traits::size_type;using difference_type = typename _Alty_traits::difference_type;using pointer         = typename _Alty_traits::pointer;using const_pointer   = typename _Alty_traits::const_pointer;using reference       = value_type&;using const_reference = const value_type&;using iterator       = _String_iterator<_Scary_val>;using const_iterator = _String_const_iterator<_Scary_val>;using reverse_iterator       = _STD reverse_iterator<iterator>;using const_reverse_iterator = _STD reverse_iterator<const_iterator>;
*/using iterator		=	_ArrayIterator<T>;using value_type	=	T;protected:T*			_pData;						//指针,指向第一个元素size_t		_nElementCount;				//无素个数size_t		_nBufferCount;				//缓冲元素个数size_t		_nDefaultBufferCount = 8;	//缺省缓冲数量size_t		_nAutoBufferCount = 0;		//自动设置缓冲次数的计数器public:static const int npos = -1;//-----------------------------------------------------------------------------------------------------------构造与析构函数
public: /// <summary>/// vector<int> ivec(10,-1);  //10个int元素,每个都初始化为-1/// </summary>/// <param name="nElementCount">元素数量</param>/// <param name="tDefaultValue">默认值</param>/// 创建时间:????-??-??    最后一次修改时间:2024-09-15 inline explicit _Array(const size_t& nElementCount = 0, const T& tDefaultValue = T()){/*构造函数中不能调用虚函数指的是直接或者隐式使用 this指针调用虚函数由于,不能确定this指针所代表的对象,包括其中指向虚函数表的指针,有没有构造完成,即包括指向虚函数表的指针在内的所有成员有没有,完全构造完成,所以难以正常使用虚函数。更重要的就是一些指针,还没有构造的时候,就用到了--这是野指针--,结果不确定!!!比如有一个 char指针,起到类似 string 的作用,只是需要动态分配内存,没有分配内存时,就是个野指针,一旦 使用的虚函数,使用了这个指针,后果就很严重。更严重的问题是,基类对子类的虚函数,如何使用完全没有谱,因为子类还没有定义。而且没有任何标志,表示虚函数表指针构造完成。虚函数没法调用。有标志也不行,子类会更改,虚函数表指针;虚函数表指针,会随着父类->子类;逐层构造,逐渐更改。PS:关于2.构造函数中调用结果运行行为正常,即已具有正常多态行为(因为在进入构造函数函数体之前,构造对象的虚函数表,对象中虚函数表指针,对象成员都已初始化完成,已是完整的派生类对象)。这个说法有问题,父类正在构造时候,子类对象,并没有开始构造,父类对象构造完成后,才会开始子类的构造,这时才会把虚函数表的指针,改成子类的虚函数表指针,这是单继承。多继承更复杂。*/#ifdef _ARRAY_DEBUG__cout << _t("inline explicit _Array(const size_t& nElementCount, const T& tDefaultValue = T())\n");#endifInitData(nElementCount,0,tDefaultValue,true,false);  //子类的InitData虚函数还未构造}/// <summary>/// 拷贝nCount个T数据到数组,默认还有8个T数据缓冲被初始化为零。/// </summary>/// <param name="pType">数据类型指针</param>/// <param name="nCount">数据个数</param>/// <param name="nDefaultBuffer">默认缓冲个数</param>/// <param name="bZeroBuffer">是否初始化缓冲为0</param>/// 创建时间:????-??-??    最后一次修改时间:2024-09-05 inline explicit _Array(const T* pType, const int nCount, const int nDefaultBuffer = 8, bool bZeroBuffer = true){
#ifdef _ARRAY_DEBUG__cout << _t("调用构造函数:_Array<T>::_Array(const T* pType, const int nCount, const int nDefaultBuffer = 8), 参数:") << _geti(nCount) << _geti(nDefaultBuffer) << _t("\n");
#endif_nDefaultBufferCount = nDefaultBuffer;InitData(0,nCount + _nDefaultBufferCount);Add(pType, nCount);if (bZeroBuffer)ZeroBufferAll();}inline _Array(const _Array& rhs){
#ifdef _ARRAY_DEBUG__cout << _t("调用构造函数: _Array<T>::_Array(const _Array& rhs)\n");
#endifif (&rhs == this || rhs._nElementCount == 0) {InitData(0);return;}_nDefaultBufferCount = rhs._nDefaultBufferCount;_nBufferCount = rhs._nBufferCount;_nElementCount = rhs._nElementCount;_pData = _Memory::New<T>(_nElementCount + _nBufferCount);_Memory::Copy(_pData, rhs._pData, _nElementCount);}/*C++11中新特性之:initializer_list详解C++11提供的新类型,定义在<initializer_list>头文件中。template< class T >class initializer_list;先说它的用处吧,然后再详细介绍一下。首先有了initializer_list之后,对于STL的container的初始化就方便多了,比如以前初始化一个vector需要这样:int a[] = {0, 1, 2, 3};std::vector<int> vec(a, a+sizeof(a));或者std::vector<int> vec;vec.push_back(1);vec.push_back(3);vec.push_back(3);vec.push_back(2);有了initializer_list后,就可以直接像初始化数组一样:复制代码class Test {private:static std::map<string, string> const nameToBirthday = {{"lisi", "18841011"},{"zhangsan", "18850123"},{"wangwu", "18870908"},{"zhaoliu", "18810316"},};}复制代码当然啦,里面的std::map必须提供参数为initializer_list的构造函数如:*/inline _Array(std::initializer_list<T> aList){InitData(0,aList.size() + _nDefaultBufferCount);Add(aList.begin(), aList.size());}/// <summary>/// /// </summary>/// <param name="v"></param>/// 创建时间:2024-07-01    最后一次修改时间:2024-07-01inline _Array(const std::vector<T>& v) {InitData(0,v.size() +_nDefaultBufferCount );for (const auto& tValue : v) {Add(tValue);}}/// <summary>/// /// </summary>/// <returns></returns>/// 创建时间:2023-05-03    最后一次修改时间:2023-05-03   inline _ArrayIterator<T> begin()const { return _ArrayIterator<T>(_pData); }/// <summary>/// /// </summary>/// <returns></returns>/// 创建时间:2023-05-03    最后一次修改时间:2023-05-03   inline _ArrayIterator<T> end()const{//迭代器使用的语句//for (_ArrayIterator<int> f = dl.begin(); f != dl.end(); f++) {       }return _ArrayIterator<T>(_pData + _nElementCount);}//-------------------------------------------------------------------------------------------------------------操作符重载
public:inline _Array<T>& operator=(const _Array<T>& rhs){if (&rhs != this){if ( &rhs != null && rhs._nElementCount != 0){_Memory::Delete<T>(_pData, _nElementCount + _nBufferCount);_nDefaultBufferCount = rhs._nDefaultBufferCount;_nBufferCount = rhs._nBufferCount;_nElementCount = rhs._nElementCount;_pData = _Memory::New<T>(_nElementCount + _nBufferCount);_Memory::Copy(_pData, rhs._pData, _nElementCount + _nBufferCount);}else{ClearMemory();}}return *this;}//重载的下标操作符inline T& operator[](const int& nIndex)const{
#ifdef _ARRAY_DEBUG_assert(nIndex < _nElementCount);
#endifreturn _pData[nIndex];}inline bool operator==(const _Array<T>& rhs) const{if (_pData == rhs._pData) return true;  //排除 相同引用  class aValue;    if( aValue == aValue)if (_pData == nullptr || rhs._pData == nullptr) return false;if (_nElementCount != rhs._nElementCount) return false;for (int n = 0; n < rhs._nElementCount; ++n){if (_pData[n] != rhs._pData[n]) return false;}return true;}inline bool operator!=(const _Array& rhs) const{return (*this == rhs ? false : true);}/*//模板类的友元函数,这里的的T跟T,是独立于类_Array<T>的template<typename T>friend bool operator== (const _Array<T>& lhs, const _Array<T>& rhs);template<typename T>friend bool operator!= (const _Array<T>& lhs, const _Array<T>& rhs);*/#if _CLR_/// <summary>/// /// </summary>/// <param name="arr"></param>/// 创建时间: 2022-12-25      最后一次修改时间:2022-12-25   inline _Array(cli::array<T>^ arr){InitData(0,arr->Length + 8);for each (T t in arr){Add(t);}}/// <summary>/// /// </summary>/// 创建时间: 2022-12-25      最后一次修改时间:2022-12-25  inline  operator cli::array<T>^ () const{cli::array<T>^ arr	= gcnew cli::array<T>(_nElementCount);for (int i = 0; i < _nElementCount; ++i){  arr[i] = _pData[i];}return arr;	 }#endifpublic://-----------------------------------------------------------------------------------------------------属性/// <summary>/// 内存大小,以 byte 为单位。/// </summary>/// <returns></returns>inline int GetMemoryLength()const { return sizeof(T) * (_nElementCount + _nBufferCount); }/// <summary>/// 字符串长度/// </summary>__declspec(property(get = GetMemoryLength)) const int MemoryLength;inline int GetDataMemoryLength()const { return sizeof(T) * _nElementCount; }/// <summary>/// 数据占用的内存长度,以 byte 为单位。/// </summary>__declspec(property(get = GetDataMemoryLength)) const int DataMemoryLength;/// <summary>/// vector 容器的容量(用 capacity 表示),指的是在不分配更多内存的情况下,/// 容器可以保存的最多元素个数;而 vector 容器的大小(用 size 表示),/// 指的是它实际所包含的元素个数。	对于一个 vector 对象来说,通过该模板类提供的 /// capacity() 成员函数,可以获得当前容器的容量;通过 size() 成员函数,可以获得容器当前的大小/// </summary>/// <returns></returns>inline int Capacity()const { return _nElementCount + _nBufferCount; }/// <summary>/// 每次重新分配内存缺省缓冲数量/// </summary>/// <returns></returns>inline int DefaultBuffer() const { return _nDefaultBufferCount; }/// <summary>/// 剩余缓冲数量/// </summary>/// <returns></returns>inline int Buffer() const { return _nBufferCount; }//设置缺省缓冲数量inline void DefaultBuffer(const int& nDefaultBuffer) { _nDefaultBufferCount = nDefaultBuffer; }//是否为空inline bool IsEmpty() { return _nElementCount == 0; }//----------------------------------------------------------------------------------------------------操作//查找元系的最大值inline const T* Min() const { return _Math::Min<T>(_pData, _nElementCount); }//查找元系的最小值inline const T* Max() const { return _Math::Max<T>(_pData, _nElementCount); }//开始位置inline  T* Begin()const { return _pData; }// 结束位置inline  T* End()const { return _pData + _nElementCount; }/// <summary>/// 返回一个翻转的数组/// </summary>/// <returns></returns>/// 创建时间:2023-05-01    最后一次修改时间:2023-05-01 inline _Array<T> Reverse()const{_Array<T> arrResult(_nElementCount);	for (int i = _nElementCount - 1; i >= 0; --i){arrResult.Add(_pData[i]);}return arrResult;}//---------------------------------------------------------------------------------------------------------虚拟函数,子类重写
protected:/// <summary>/// 初始化数据/// </summary>/// <param name="nElementCount">元素个数</param>/// <param name="nBufferCount">缓冲个数</param>/// <param name="tDefaultValue">元素默认值</param>/// <param name="bDefaultValue">是否设置元素默认值</param>/// <param name="bInitBuffer">是否初始化缓冲</param>/// 创建时间:????-??-??    最后一次修改时间:2024-09-15 inline virtual void InitData(const size_t& nElementCount = 0,const size_t& nBufferCount = 0,const T& tDefaultValue = T(),const bool& bDefaultValue= false,const bool& bInitBuffer = false){ _nBufferCount = nBufferCount;_nElementCount = nElementCount;_pData = null;if (_nElementCount + _nBufferCount > 0) {//分配内存_pData = _Memory::New<T>(_nElementCount + _nBufferCount);//初始化数据if (bDefaultValue) {for (size_t n = 0; n < _nElementCount; ++n) {*(_pData + n) = tDefaultValue;}}//初始化缓冲if (bInitBuffer) {for (size_t n = _nElementCount; n < _nElementCount + _nBufferCount; ++n) {*(_pData + n) = T();}}}		#ifdef _ARRAY_DEBUG__cout << _t("inline virtual void _Array<T>::InitData") << _t("\n");
#endif}public:/// <summary>/// _Array<_char> *ps = new LString("abc");  delete ps; /// 如果_Array的析构函数不用virtual,则上属语句LString的虚拟函数不会被调用/// 虚析构函数的作用是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。/// 当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器/// 会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一/// 个类被用来作为基类的时候,才把析构函数写成虚函数。/// </summary>inline virtual ~_Array(){
#ifdef _ARRAY_DEBUG__cout << _t("_Array<T>::~_Array()\n");
#endifClearMemory();}/// <summary>/// 添加一串元素,pData为数据指针,nLength数据长度/// </summary>/// <param name="pData"></param>/// <param name="nLength"></param>/// <returns></returns>inline virtual _Array<T>& Add(const T* pData, const int& nLength){#ifdef _ARRAY_DEBUG_//_cout << _t("调用函数:inline virtual const T* add(const T* pData, const int nLength)\t参数:") << _geti(nLength) << _t("\n");;
#endif	 /*#ifdef  _STR_DEBUG__cout << _t("_Str<T>:\t inline  const _Str<T>& Add(const T& aChar) 参数:") << _geti(aChar) << _t("\n");
#endif //要判断 *pData == 0 防止  str_.Add(L"\0",1); if (aChar == 0) { return *this; }if (_nBufferCount >= 1){_pData[_nElementCount] = aChar;_nBufferCount -= 1;_nElementCount += 1;_pData[_nElementCount] = 0;}else{SetBuffer(1 + _nDefaultBufferCount * _Math::Pow(2, _nAutoBufferCount)); //自动设置缓冲次数加 if (_nBufferCount >= 1){_pData[_nElementCount] = aChar;_nBufferCount -= 1;_nElementCount += 1;_pData[_nElementCount] = 0;}else{throw _t("设置缓冲区失败!");}++_nAutoBufferCount;}return *this;}*/if (pData == null || nLength <= 0) return *this;if (_nBufferCount >= nLength){_Memory::Copy<T>(_pData + _nElementCount, pData, nLength);_nBufferCount -= nLength;_nElementCount += nLength;}else{	SetBuffer(nLength + _nDefaultBufferCount * _Math::pow(2, _nAutoBufferCount)); //自动设置缓冲次数加 if (_nBufferCount >= nLength){_Memory::Copy<T>(_pData + _nElementCount, pData, nLength);				 _nBufferCount -= nLength;_nElementCount += nLength;				 }else{throw _t("设置缓冲区失败!");}++_nAutoBufferCount;}return *this;}/// <summary>/// 添加单个元素/// </summary>/// <param name="rData"></param>/// <returns></returns>inline _Array<T>& Add(const T& rData){	return Add(&rData, 1);	}/// <summary>/// 添加一个数组/// </summary>/// <param name="arr"></param>/// <returns></returns>inline _Array<T>& Add(const _Array<T>& arr){return Add(arr.DataConst, arr.Length);}//删除元系,nStartPos为开始位置,nLength长度inline virtual const T* Del(const int& nStartPos, const int& nLength){if (nStartPos + nLength > _nElementCount){_nBufferCount = _nBufferCount + _nElementCount - nStartPos;_nElementCount = nStartPos + 1;}else if (nStartPos + nLength >= _nElementCount){_nElementCount -= nLength;_nBufferCount += nLength;}else{for (int n = nStartPos + nLength; n < _nElementCount; ++n){_pData[n - nLength] = _pData[n];}_nElementCount -= nLength;_nBufferCount += nLength;}return _pData;}/// <summary>/// 清空所有内存,并把指针设为null/// </summary>inline virtual void ClearMemory() override{#ifdef _ARRAY_DEBUG_//_cout << _t("void _Array<T>::ClearData()\n");#endifif (_nElementCount + _nBufferCount > 0 && _pData != null) {_Memory::Delete<T>(_pData, _nElementCount + _nBufferCount);}else {if (_pData != null) {throw "_pData != null";}}_pData = null;_nBufferCount = 0;_nElementCount = 0;}/// <summary>/// 清空数据,但不释放内存,只是把数据计数器重设为0。/// </summary>inline virtual void ClearData()override{_nBufferCount = _nBufferCount + _nElementCount;_nElementCount = 0;}/// <summary>///  设置缓冲数,如果原来缓冲区数量大于新设置的数量,则不设置。/// </summary>/// <param name="nBufferCount"></param>/// <param name="bZeroBuffer"></param>/// 创建时间:????-??-??    最后一次修改时间:2023-03-11 inline virtual void SetBuffer(const int& nBufferCount, const bool& bZeroBuffer = false){#ifdef _ARRAY_DEBUG__cout << _t("调用函数:inline virtual void SetBuffer(const int& nBufferCount)\t参数:") << _geti(nBufferCount) <<_t("\n");
#endif	 if (_nBufferCount >= nBufferCount) return;if (nBufferCount == 0) return;T* pNew = _Memory::New<T>(_nElementCount + nBufferCount);if (_nElementCount > 0)_Memory::Copy(pNew, _pData, _nElementCount);_Memory::Delete<T>(_pData, _nElementCount + _nBufferCount);_pData = pNew;_nBufferCount = nBufferCount;if (bZeroBuffer)ZeroBufferAll();}/// <summary>/// 转为String表示/// </summary>/// <returns></returns>/// 创建时间:2023-04-29    最后一次修改时间:2024-08-17inline virtual _string ToSplitString(const _string& sSplitString)  const override{  				_string sResult;_string sp = sSplitString.Length == 0 ? _string(_t(",")) : sSplitString;sResult.Add(_t("{"));if (_nElementCount > 0){for (int i = 0; i < _nElementCount - 1; ++i){sResult.std_append(_Convert::to_string_t<T>(_pData[i]));sResult.std_append(sp);}sResult.std_append(_Convert::to_string_t<T>(_pData[_nElementCount - 1]));}sResult.Add(_t("}"));return sResult;}inline _string ToString()const{return ToSplitString("");}/// <summary>/// 强制转换为String/// </summary>/// 创建时间:2023-04-29    最后一次修改时间:2023-04-29operator _stdstr()const{return ToString().std_c_str();}public: //从nStart开始向后查找aTypeValue第一次出现在当前容器中的位置,失败时返回_Array::nposinline int find(const T& aTypeValue, const int nStart = 0) const { return _Math::find(_pData, _nElementCount, &aTypeValue, 1, nStart); }//从nStart开始向后查找长度为pFindLength的pFind数据第一次出现在当前容器中的位置,失败时返回_Array::nposinline int find(const T* pFind, const int& nStart, const int& pFindLength) const { return _Math::find(_pData, _nElementCount, pFind, pFindLength, nStart); }//从nStart开始向后查找aFindLLinearList第一次出现在当前容器中的位置,失败时返回_Array::npos int find(const _Array& aFindLLinearList, const int& nStart = 0) const { return _Math::find(_pData, _nElementCount, aFindLLinearList._pData, aFindLLinearList._nElementCount, nStart); }//从nStart开始向前查找aTypeValue第一次出现在当前容器中的位置,失败时返回_Array::npos。inline int rfind(const T& aTypeValue, const int& nStart = npos) const { return _Math::rfind(_pData, _nElementCount, &aTypeValue, 1, nStart); }//从nStart开始向前查找长度为pFindLength的pFind数据第一次出现在当前容器中的位置,失败时返回_Array::nposinline int rfind(const T* pFind, const int& nStart, const int& pFindLength) const { return _Math::rfind(_pData, _nElementCount, pFind, pFindLength, nStart); }//从nStart开始向前查找aFindLLinearList第一次出现在当前容器中位置,失败时返回_Array::npos inline int rfind(const _Array& aFindLLinearList, const int& nStart = npos) const { return _Math::rfind(_pData, _nElementCount, aFindLLinearList._pData, aFindLLinearList._nElementCount, nStart); }//从nStart开始向后查找aTypeValue第一次出现的位置,失败时返回_Array::nposinline int find_First_of(const T& aTypeValue, const int& nStart = 0) const { return _Math::find_First_of(_pData, _nElementCount, &aTypeValue, 1, nStart); }//从nStart开始向后查找长度为pFindLength的pFind数据任一元素第一次出现的位置,失败时返回_Array::nposinline int find_First_of(const T* pFind, const int& nStart, const int& pFindLength) const { return _Math::find_first_of(_pData, _nElementCount, pFind, pFindLength, nStart); }//从nStart开始向后查找aFindLLinearList任一元素第一次出现的位置,失败时返回_Array::npos inline int find_First_of(const _Array& aFindLLinearList, const int& nStart = 0) const { return _Math::find_first_of(_pData, _nElementCount, aFindLLinearList._pData, aFindLLinearList._nElementCount, nStart); }//从nStart开始向后查找aTypeValue第一次不出现的位置,失败时返回_Array::nposinline int find_First_not_of(const T& aTypeValue, const int& nStart = 0) const { return _Math::find_first_not_of(_pData, _nElementCount, &aTypeValue, 1, nStart); }//从nStart开始向后查找长度为pFindLength的pFind数据任一元素第一次不出现的位置,失败时返回_Array::nposinline int find_First_not_of(const T* pFind, const int& nStart, const int& pFindLength) const { return _Math::find_first_not_of(_pData, _nElementCount, pFind, pFindLength, nStart); }//从nStart开始向后查找aFindLLinearList任一元素第一次不出现的位置,失败时返回_Array::npos inline int find_First_not_of(const _Array& aFindLLinearList, const int& nStart = 0) const { return _Math::find_first_not_of(_pData, _nElementCount, aFindLLinearList._pData, aFindLLinearList._nElementCount, nStart); }//从nStart开始向前查找aTypeValue第一次出现的位置,成功返回索引处,失败时返回_Array::nposinline int find_last_of(const T& aTypeValue, const int& nStart = 0) const { return _Math::find_last_of(_pData, _nElementCount, &aTypeValue, 1, nStart); }//从nStart开始向前查找pFind中元系第一次出现的位置,成功返回索引处,失败时返回_Array::nposinline int find_last_of(const T* pFind, const int& nStart, const int& pFindLength) const { return _Math::find_last_of(_pData, _nElementCount, pFind, pFindLength, nStart); }//从nStart开始向前(倒序)查找aFindLLinearList任一元素第一次出现的位置,找到返回索引处,失败时返回_Array::nposinline int find_last_of(const _Array& aFindLLinearList, const int& nStart = 0) const { return _Math::find_last_of(_pData, _nElementCount, aFindLLinearList._pData, aFindLLinearList._nElementCount, nStart); }//从nStart开始向前查找aTypeValue第一次不出现的位置,失败时返回_Array::nposinline int find_last_not_of(const T& aTypeValue, const int& nStart = 0) const { return _Math::find_last_not_of(_pData, _nElementCount, &aTypeValue, 1, nStart); }//从nStart开始向前查找长度为pFindLength的pFind数据任一元素第一次不出现的位置,失败时返回_Array::nposinline int find_last_not_of(const T* pFind, const int& nStart, const int& pFindLength) const { return _Math::find_last_not_of(_pData, _nElementCount, pFind, pFindLength, nStart); }//从nStart开始向前查找aFindLLinearList任一元素第一次不出现的位置,失败时返回_Array::npos inline int find_last_not_of(const _Array& aFindLLinearList, const int& nStart = 0) const { return _Math::find_last_not_of(_pData, _nElementCount, aFindLLinearList._pData, aFindLLinearList._nElementCount, nStart); }public:/// <summary>/// 临时整型数据,方法函数调用。/// </summary>int TmepEffectiveCount = 0;/// <summary>/// 把有效长度后一位数据进行初始化,如果是数字,则会自动初始化0。/// </summary>inline void ZeroBufferOne() {if (this->_nBufferCount > 0)this->_pData[this->_nElementCount] = T();}/// <summary>/// 初始化剩下的缓冲区/// </summary>inline void ZeroBufferAll() {if (this->_nBufferCount > 0){for (int i = 0; i < _nBufferCount; ++i){_pData[i + _nElementCount] = T();}}}/// <summary>/// 重新设置元素的长度,这个长度不能超过 OldLength + Buffer/// </summary>/// <param name="nNewLength"></param>/// 创建时间:????-??-??    最后一次修改时间:????-??-??(2024/04/21)inline void ResetLength(const int& nNewLength) {if (nNewLength > this->Capacity()) {_char  sError[] = _t("新设置的长度已超过容器的最大长度!\n");_cout << _t("_Mem::ResetLength") << sError;throw sError;}int iCap = this->Capacity();this->_nBufferCount = iCap - nNewLength;this->_nElementCount = nNewLength;}/// <summary>/// 除非内存给其它对象托管,否则不要调用这个函数。/// 放置对象当前使用的内存,可能内存已托管给别的对象,/// 重新初始化当前对象/// </summary>/// 创建时间:2022-12-29    最后一次修改时间:2022-12-29inline virtual void GiveUpMem(){this->InitData(0);}/// <summary>/// 返回有nCount个元素的数组。/// </summary>/// <param name="nCount"></param>/// <returns></returns>/// 创建时间:2023-12-10    最后一次修改时间:2023-12-10   已测试static inline _Array<T> newElement(const size_t& nCount){_Array<T> tmp(nCount); //设置nCount个缓冲//把缓冲变成元素tmp._nBufferCount = 0; tmp._nElementCount = nCount;return tmp;  //此处C++编译器直接返回tmp对象,不会再构造一个_Array<T>.}public://----------------------------------------------------------------属性  inline T* GetData() { return this->_pData; }__declspec(property(get = GetData)) T* Data;inline const T* GetDataConst() const { return  this->_pData; }__declspec(property(get = GetDataConst)) const T* DataConst;/// <summary>/// 数组长度,无素个数/// </summary>__declspec(property(get = GetLength)) int Length;/// <summary>/// 有效元素的个数/// </summary>/// <returns></returns>inline int GetLength()const { return _nElementCount; }/// <summary>/// 自动分配内存次数/// </summary>/// 创建时间:2024-08-18    最后一次修改时间:2024-08-18__declspec(property(get = GetAutoBufferCount)) size_t AutoBufferCount;inline const size_t& GetAutoBufferCount()const{ return _nAutoBufferCount; }}; //-------------------------------------------------------------------------------------_Array#ifdef _UNICODE_template<class T>
std::wistream& operator >> (std::wistream& os, _Array<T>& arr)
{_cout << _t("std::wistream& operator >> (std::wistream& os, _Array<T>& aString){未完成!\n");return os;
}template<class T>
std::wostream& operator<<(std::wostream& os, const _Array<T>& arr)
{os << arr.ToString();return os;
}#else
template<class T>
std::istream& operator >> (std::istream& os, _Array<T>& aString)
{_cout << _t("std::wistream& operator >> (std::wistream& os, _Array<T>& aString){未完成!\n");return os;
}template<class T>
std::ostream& operator<<(std::ostream& os, const _Array<T>& arr)
{os << arr.ToString();return os;
}#endif_LF_END_ //------------------------------------------------------------------------------_LF_END_ #endif // !_ARRAY_H_

_ByteArray.h

/*******************************************************************************************
文件名						: _ByteArray.h作者							: 李锋功能							: 字节数组创建时间						: 2022年01月01日最后一次修改时间				:  2022年01月05日
********************************************************************************************/#ifndef __BYTEARRAY_H_
#define __BYTEARRAY_H_#include "_Array.h"
#include "_StrA.h"
#include "_StrW.h"_LF_BEGIN_/// <summary>
/// _Byte 数组
/// </summary>
class _ByteArray final : public _Array<_byte>
{
public:explicit _ByteArray(int nBuffer = 0) : _Array<_byte>(nBuffer) {}explicit _ByteArray(const _ByteArray& ba, const size_t&  nCount);
public:void TrusteeshipMem(const _byte* pData, const int nDataMemoryLength, const int& nMemoryLength);void TrusteeshipMem(_string& sText);void TrusteeshipMem(_ByteArray& ba);//int AddString(const _string& S);int AddStringA(const _StrA& s);int AddStringW(const _StrW& s);int AddFloat(const float& fValue);int AddInt(const int& iValue);int AddInt64(const __int64& iValue);int AddByte(const _byte& bValue);//_string  ReadString(const int& nPos, const int& nLength);_StrA  ReadStringA(const int& nPos, const int& nLength);_StrW  ReadStringW(const int& nPos, const int& nLength);bool ReadFromFile(const _char* sFileName);bool WriteToFile(const _char* sFileName);/// <summary>/// 类型转换,转换成T类型/// </summary>/// <typeparam name="T"></typeparam>/// <param name="nStart">指针开始位置</param>/// <returns>返回T类型的引用</returns>/// 创建时间:2024-08-12    最后一次修改时间:2024-08-12template<class T> const T& ToAny(const size_t& nStart = 0)const{lassert( _nElementCount >= nStart + sizeof(T)   ,"转换的数据太大了,大于数组本身所分配的内存。");T* pt = (T*)_pData + nStart;return *pt;}/// <summary>/// 转换为宽字符串/// </summary>/// <returns></returns>/// 创建时间:2024-08-12    最后一次修改时间:2024-08-12const _string ToWString()const;
};_LF_END_  //------------------------------------------------------------------------------------------_LF_END_#endif  //------------------------------------------------------------------- #endif 

_ByteArray.cpp

#include "_ByteArray.h"
#include "global_c_all.h"_LF_BEGIN__ByteArray::_ByteArray(const _ByteArray& ba, const size_t& nCount)
{if (nCount >= ba.Length){Add(ba);}else{_Array<_byte>::Add(ba.DataConst, nCount);}
}/// <summary>
/// 释放本身内存,托管新的内存。
/// </summary>
/// <param name="pData"></param>
/// <param name="nDataMemoryLength">数据长度</param>
/// <param name="nMemoryLength">使用内存长度</param>
/// 创建时间:2023-01-04    最后一次修改时间:2023-01-05
void _ByteArray::TrusteeshipMem(const _byte* pData, const int nDataMemoryLength, const int& nMemoryLength)
{ClearMemory();  //清除内存_nBufferCount = nMemoryLength - nDataMemoryLength;if (_nBufferCount < 0){throw _t("托管内存错误!");}_pData = (_byte*)pData;_nElementCount = nDataMemoryLength;
}/// <summary>
/// 托管String对象,并放本身内存。
/// </summary>
/// <param name="sText"></param>
/// 创建时间:2023-01-04    最后一次修改时间:2023-01-05
void _ByteArray::TrusteeshipMem(_string& sText)
{TrusteeshipMem((const _byte*)sText.Data, sText.DataMemoryLength, sText.MemoryLength);sText.GiveUpMem();
}/// <summary>
/// 释放本身内存,托管其它对象
/// </summary>
/// <param name="ba"></param>
/// 创建时间:2023-01-04    最后一次修改时间:2023-01-05
void _ByteArray::TrusteeshipMem(_ByteArray& ba)
{TrusteeshipMem((const _byte*)ba.Data, ba.GetDataMemoryLength(), ba.GetMemoryLength());ba.GiveUpMem();
}/*
int  _ByteArray::AddString(const _string& s)
{if (s.Length == 0) return -1;int nPos = Length;Add((_byte*)s.Data, (int) (sizeof(_char) * s.Length) );return nPos;}
*/
int _ByteArray::AddStringA(const _StrA& s)
{if (s.Length == 0) return -1;int nPos = _nElementCount;Add((_byte*)s.Data, (int)(sizeof(char) * s.Length));return nPos;
}int _ByteArray::AddStringW(const _StrW& s)
{if (s.Length == 0) return -1;int nPos = _nElementCount;Add((_byte*)s.Data, (int)(sizeof(wchar_t) * s.Length));return nPos;
}int _ByteArray::AddFloat(const float& fValue)
{int nPos = _nElementCount;Add((_byte*)&fValue, sizeof(float));return nPos;
}int _ByteArray::AddInt(const int& iValue)
{int nPos = _nElementCount;Add((_byte*)&iValue, sizeof(int));return nPos;
}int _ByteArray::AddInt64(const __int64& iValue)
{int nPos = _nElementCount;Add((_byte*)&iValue, sizeof(__int64));return nPos;
}int _ByteArray::AddByte(const _byte& bValue)
{int nPos = _nElementCount;Add(&bValue, sizeof(_byte));return nPos;
}/*
_string _ByteArray::ReadString(const int& nPos, const int& nLength)
{int n = nLength / sizeof(_char);return _string( (_char*) (_pData + nPos), n);
}
*/_StrA _ByteArray::ReadStringA(const int& nPos, const int& nLength)
{int n = nLength / sizeof(char);return _StrA((char*)(_pData + nPos), n);
}_StrW _ByteArray::ReadStringW(const int& nPos, const int& nLength)
{int n = nLength / sizeof(wchar_t);return _StrW((wchar_t*)(_pData + nPos), n);
}bool _ByteArray::ReadFromFile(const _char* sFileName)
{return ga.ReadFileToBuffer<_byte>(sFileName, *this);}bool _ByteArray::WriteToFile(const _char* sFileName)
{return ga.WriteFile<_byte>(sFileName, *this);
}const _string _ByteArray::ToWString() const
{	 return (wchar_t*)_pData;
}_LF_END_

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/141538.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

基础物理-直线运动2

2-1 位置、位移和平均速度 位置与位移 为了确定物体的位置&#xff0c;通常需要相对于某个参考点来测量&#xff0c;这个参考点通常是某个坐标轴的原点&#xff08;或零点&#xff09;&#xff0c;如图 2-1 中的 x 轴。坐标轴的正方向是坐标增大的方向&#xff0c;在图 2-1 中…

掌握远程管理的艺术:揭秘Python的pywinrm库

文章目录 &#x1f525; 掌握远程管理的艺术&#xff1a;揭秘Python的pywinrm库 &#x1f525;背景&#xff1a;为何选择pywinrm&#xff1f;pywinrm库简介安装pywinrm库简单库函数使用方法场景应用常见问题与解决方案总结 &#x1f525; 掌握远程管理的艺术&#xff1a;揭秘Py…

【ARM】Cache深度解读

Cache的基本概念和使用场景 不同的Master硬件共享数据时—invalid cache 外设和DDR之间没有cache&#xff0c;所以外设直接把数据写入DDR中&#xff0c;但是cpu和DDR之间有cache&#xff0c;cpu会首先访问cache&#xff0c;如果命中直接从cache中拿数据&#xff0c;但是此时的…

浪潮信息首推3秒智能控温!告别服务器开机噪音

在当前的数据中心运维实践中&#xff0c;运维人员在部署服务器时常被“飞机起飞”般的开机噪音所困扰。服务器刚刚接通电源&#xff0c;其内部元件尚处于预热待命状态&#xff0c;而风扇却已全速运转&#xff0c;这不仅加剧了噪音污染&#xff0c;还拖慢了启动速度&#xff0c;…

[数据集][目标检测]智慧交通铁路人员危险行为躺站坐检测数据集VOC+YOLO格式3766张4类别

图片数量(jpg文件个数)&#xff1a;3766 标注数量(xml文件个数)&#xff1a;3766 标注数量(txt文件个数)&#xff1a;3766 标注类别数&#xff1a;4 标注类别名称:["sitting","sleeping","standing","track"] 每个类别标注的框数&…

OpenCore Legacy Patcher 2.0.0 发布,83 款不受支持的 Mac 机型将能运行最新的 macOS Sequoia

在不受支持的 Mac 上安装 macOS Sequoia (OpenCore Legacy Patcher v2.0.0) Install macOS on unsupported Macs 请访问原文链接&#xff1a;https://sysin.org/blog/install-macos-on-unsupported-mac/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主…

《深度学习》PyTorch 手写数字识别 案例解析及实现 <下>

目录 一、回顾神经网络框架 1、单层神经网络 2、多层神经网络 二、手写数字识别 1、续接上节课代码&#xff0c;如下所示 2、建立神经网络模型 输出结果&#xff1a; 3、设置训练集 4、设置测试集 5、创建损失函数、优化器 参数解析&#xff1a; 1&#xff09;para…

一篇文章带你入门机器学习 Part1 -->Machine Learning from Scratch

学习网站&#xff1a;Machine Learning from Scratch Machine Learning from Scratch (Part1神经网络&#xff09; 神经网络——Neural Networks神经网络是如何工作的&#xff1f;训练神经网络 神经网络——Neural Networks 在人工神经网络的背景下&#xff1a;一个神经元是一…

全面理解tensor编程中矩阵的行和列

经常会在编程中遇到理解矩阵行和列的事情。 1、要明确无论这个张量有多少维度&#xff0c;它的矩阵乘法都只能作用于最后两个维度。 例如&#xff1a; import torcha torch.rand([64, 32, 3, 4]) b torch.rand([64, 32, 3, 4])c torch.matmul(a, b.transpose(2, 3)) # 交…

备战软考Day02-数据结构与算法

1.基本概念与三要素 1.什么是数据 数据是信息的载体&#xff0c;是描述客观事物属性的数、字符及所有能输入到计算机中并被计算机程序识别和处理的符号的集合。数据是计算机程序加工的原料。 2.数据元素、数据项 数据元素是数据的基本单位&#xff0c;通常作为一个整体进行…

18062 二维数组每行中的最大值

### 思路 1. 使用指针变量遍历二维数组的每一行。 2. 对于每一行&#xff0c;找到该行的最大值。 3. 输出每一行的最大值。 ### 伪代码 1. 定义一个指向二维数组的指针变量 p。 2. 遍历二维数组的每一行&#xff1a; - 将 p 指向当前行。 - 初始化 max 为当前行的第一个…

探索Python轻量级数据库:TinyDB的奇妙之旅

文章目录 探索Python轻量级数据库&#xff1a;TinyDB的奇妙之旅背景&#xff1a;为何选择TinyDB&#xff1f;什么是TinyDB&#xff1f;如何安装TinyDB&#xff1f;简单库函数使用方法场景应用常见Bug及解决方案总结 探索Python轻量级数据库&#xff1a;TinyDB的奇妙之旅 背景&…

10.4K Star,高性能富文本编辑器

Hi&#xff0c;骚年&#xff0c;我是大 G&#xff0c;公众号「GitHub 指北」会推荐 GitHub 上有趣有用的项目&#xff0c;一分钟 get 一个优秀的开源项目&#xff0c;挖掘开源的价值&#xff0c;欢迎关注。 在现代 Web 开发中&#xff0c;富文本编辑器是不可或缺的一部分&…

Java设计模式—面向对象设计原则(六) ----->合成复用原则(CRP) (完整详解,附有代码+案例)

文章目录 3.6 合成复用原则(CRP)3.6.1 概述3.6.2 案列 3.6 合成复用原则(CRP) 合成复用原则(CRP)&#xff1a;Composite Reuse Principle&#xff0c;CRP 又叫&#xff1a; 组合/聚合复用原则&#xff08;Composition/Aggregate Reuse Principle&#xff0c;CARP&#xff09;…

java中的注解原理是什么?

Java中的注解&#xff08;Annotations&#xff09;是一种用于提供元数据的机制。它可以通过在代码中添加注解的形式&#xff0c;将一些额外的信息嵌入到代码里。注解本质上不会改变程序的实际逻辑行为&#xff0c;但是可以帮助开发工具、编译器、框架等获取这些元数据&#xff…

信息学奥赛初赛天天练-90-CSP-S2023基础题2-离散数学、染色、完全三叉树、平面图、边双连通图、欧拉图、最长公共子序列、快速排序

PDF文档公众号回复关键字:20240915 2023 CSP-S 选择题 1单项选择题&#xff08;共15题&#xff0c;每题2分&#xff0c;共计30分&#xff1a;每题有且仅有一个正确选项&#xff09; 6 以下连通无向图中&#xff0c;( )一定可以用不超过两种颜色进行染色 A 完全三叉树 B 平面图…

Vue2学习笔记(01计算属性和监视属性)

1、事件修饰符 2、计算属性-computed 要显示的数据不存在&#xff0c;要通过计算得来。在computed对象中定义计算属性。在页面中使用{{方法名}}来显示计算的结果。 3、监视属性-watch 通过vm对象的$watch()或watch配置来监视指定的属性当属性变化时,回调函数自动调用,在函数内…

一文速通calcite结合flink理解SQL从文本变成执行计划详细过程

文章目录 你可以学到啥测试代码背景知识SQL转变流程图问题 你可以学到啥 SQL如何一步步变成执行计划的有哪些优化器&#xff0c;哪些优化规则calcite 和flink 如何结合的 测试代码 EnvironmentSettings settings EnvironmentSettings.inBatchMode(); TableEnvironment tabl…

非线性规划------ + 案例 + Python源码求解(见文中)

目录 一、非线性代数模型的例子eg1&#xff1a;人口增长模型&#xff08;Logistic Growth Model&#xff09;模型公式Python建模与求解代码运行结果 eg2&#xff1a;化学反应速率模型&#xff08;Michaelis-Menten方程&#xff09;模型公式Python建模与求解代码运行结果 eg3&am…

栈的应用之表达式求值(前缀、中缀、后缀)

目录 引入 1.中缀表达式的求值(两种方式) 方式一:使用两个栈直接求值 方式二:将其转换为后缀表达式求值 ①转换: ②对后缀表达式求值: 2.后缀表达式的求值(1个栈,存放运算符) 3.前缀表达式的求值(1个栈用来存放数字,相对来讲没那么重要) 引入 1.中缀表达式的…