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

news2024/11/14 13:49:47

例子:

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
	表示非连续的内存区域并通过一对指向首尾元素的指针双向链接起来,插入删除效率高,随机访问效率低

2

stl提供了三个最基本的容器: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");
			
#endif

		InitData(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");
#endif

		if (&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-01
	inline _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);
#endif
		return _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;	 
	}

#endif
 
public:
	//-----------------------------------------------------------------------------------------------------属性


	
	/// <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");
#endif
		ClearMemory();
	}



	/// <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");
	#endif
		if (_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-17
	inline 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-29
	operator _stdstr()const
	{
		return ToString().std_c_str();
	}
 
public: 
	//从nStart开始向后查找aTypeValue第一次出现在当前容器中的位置,失败时返回_Array::npos
	inline int find(const T& aTypeValue, const int nStart = 0) const { return _Math::find(_pData, _nElementCount, &aTypeValue, 1, nStart); }

	//从nStart开始向后查找长度为pFindLength的pFind数据第一次出现在当前容器中的位置,失败时返回_Array::npos
	inline 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::npos
	inline 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::npos
	inline 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::npos
	inline 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::npos
	inline 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::npos
	inline 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::npos
	inline 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::npos
	inline 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::npos
	inline 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::npos
	inline 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::npos
	inline 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-29
	inline 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-12
	template<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-12
	const _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.coloradmin.cn/o/2139799.html

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

相关文章

el-table 的单元格 + 图表 + 排序

<el-table border :data"tableDataThree" height"370px" style"width: 100%"><el-table-column :key"activeName 8" width"50" type"index" label"序号" align"center"></el…

macOS系统Homebrew工具安装及使用

1.打开Homebrew — The Missing Package Manager for macOS (or Linux) 2.复制安装命令到终端执行 复制 执行 3. 开始自动安装过程 4.安装成功 5.使用brew安装wget工具

第L6周:机器学习-随机森林(RF)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目标&#xff1a; 1.什么是随机森林&#xff08;RF&#xff09; 随机森林&#xff08;Random Forest, RF&#xff09;是一种由 决策树 构成的 集成算法 &#…

WebSocket vs. Server-Sent Events:选择最适合你的实时数据流技术

引言&#xff1a; 在当今这个信息爆炸的时代&#xff0c;用户对于网页应用的实时性要求越来越高。从即时通讯到在线游戏&#xff0c;再到实时数据监控&#xff0c;WebSocket技术因其能够实现浏览器与服务器之间的全双工通信而受到开发者的青睐。 WebSocket技术为现代Web应用…

java计算机毕设课设—电子政务网系统(附源码、文章、相关截图、部署视频)

这是什么系统&#xff1f; 资源获取方式在最下方 java计算机毕设课设—电子政务网系统(附源码、文章、相关截图、部署视频) 电子政务网系统主要用于提升政府机关的政务管理效率&#xff0c;核心功能包括前台网站展示、留言板管理、后台登录与密码修改、网站公告发布、政府部…

高级Java程序员必备的技术点:你准备好了吗?

在Java编程的世界里&#xff0c;成为一名高级程序员不仅需要深厚的基础知识&#xff0c;还需要掌握一系列高级技术和最佳实践。这些技术点是通向技术专家之路的敲门砖&#xff0c;也是应对复杂项目挑战的利器。本文将探讨高级Java程序员必备的技术点&#xff0c;帮助你自我提升…

VS code 安装使用配置 Continue

Continue 插件介绍 Continue 是一款高效的 VS Code 插件&#xff0c;提供类似 GitHub Copilot 的功能&#xff0c;旨在提升开发者的编程效率。其配置简单&#xff0c;使用体验流畅&#xff0c;深受开发者喜爱。 主要功能特点 智能代码补全 Continue 能够基于当前代码上下文生…

MATLAB 可视化基础:绘图命令与应用

目录 1. 绘制子图1.1基本绘图命令1.2. 使用 subplot 函数1.3. 绘图类型 2.MATLAB 可视化进阶(以下代码均居于以上代码的数据定义上实现)2.1. 极坐标图2.3. 隐函数的绘制 3.总结 在数据分析和科学计算中&#xff0c;数据可视化是理解和解释结果的关键工具。今天&#xff0c;我将…

Javaの运算符 Day5

1. 算数运算符 1.1 二元运算符&#xff08;两个操作数&#xff09;的算数运算符 操作符描述求和-求差*求积/求商%求余 代码举例 public class TestOperator {public static void main(String[] args) {int a 20;int b 12;System.out.println(a b);System.out.println(a …

【算法】队列与BFS

【ps】本篇有 4 道 leetcode OJ。 目录 一、算法简介 二、相关例题 1&#xff09;N 叉树的层序遍历 .1- 题目解析 .2- 代码编写 2&#xff09;二叉树的锯齿形层序遍历 .1- 题目解析 .2- 代码编写 3&#xff09;二叉树最大宽度 .1- 题目解析 .2- 代码编写 4&#xf…

UART协议

目录 一、概述二、帧格式起始位数据位奇偶校验位停止位 三、数据传输过程四、串行通信接口RS232RS422RS485 五、UART环回程序设计 参考&#xff1a;正点原子FPGA开发指南 一、概述 UART&#xff08;通用异步收发器&#xff09;是一种异步、全双工的串行通信总线&#xff0c;在…

CGAL 从DSM到DTM holefilling remeshing

CGAL 从DSM到DTM holefilling & remeshing 上一节简单地删除被建筑物覆盖的大片区域中的顶点会导致大的Delaunay三角面&#xff0c;从而得到了较差的DTM&#xff0c;所以一个额外的步骤可以帮助产生更好的形状网格:删除大于阈值的面&#xff0c;并用孔洞填充算法进行三角化…

C++速通LeetCode简单第17题-爬楼梯

思路要点&#xff1a;将问题转化为求斐波那契数列的第n项&#xff0c;然后迭代。 思路分析&#xff1a;最后一次爬的阶数不是1就是2&#xff0c;假设爬n阶的方法数是f(n)&#xff0c;假设最后一次爬1阶&#xff0c;那么爬前面的 n-1阶的方法数是f(n-1)&#xff1b;假设最后一次…

力扣题解2848

大家好&#xff0c;欢迎来到无限大的频道。 今日继续给大家带来力扣题解。 题目描述&#xff08;简单&#xff09;&#xff1a; 与车相交的点 给你一个下标从 0 开始的二维整数数组 nums 表示汽车停放在数轴上的坐标。对于任意下标 i&#xff0c;nums[i] [starti, endi] &…

熵权法详细讲解+Python代码实现

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

大数据新视界 --大数据大厂之 Cassandra 分布式数据库:高可用数据存储的新选择

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

基于单片机的超声波液位检测系统(论文+源码)

1总体设计 本课题为基于单片机的超声波液位检测系统的设计&#xff0c;系统的结构框图如图2.1所示。其中包括了按键模块&#xff0c;温度检测模块&#xff0c;超声波液位检测模块&#xff0c;显示模块&#xff0c;蜂鸣器等器件设备。其中&#xff0c;采用STC89C52单片机作为主…

2.5 Trigger源码分析 -- ant-design-vue系列

Trigger源码分析 – ant-design-vue系列 1 概述 源码地址&#xff1a; https://github.com/vueComponent/ant-design-vue/blob/main/components/vc-trigger/Trigger.tsx 在源码的实现中&#xff0c;Trigger组件主要有两个作用&#xff1a; 使用Portal组件&#xff0c;把Pop…

构建响应式 Web 应用:Vue.js 基础指南

构建响应式 Web 应用&#xff1a;Vue.js 基础指南 一 . Vue 的介绍1.1 介绍1.2 好处1.3 特点 二 . Vue 的快速入门2.1 案例 1 : 快速搭建 Vue 的运行环境 , 在 div 视图中获取 Vue 中的数据2.2 案例 2 : 点击按钮执行 vue 中的函数输出 vue 中 data 的数据2.3 小结 三 . Vue 常…

Leetcode3282. 到达数组末尾的最大得分

Every day a Leetcode 题目来源&#xff1a;3282. 到达数组末尾的最大得分 解法1&#xff1a;动态规划 代码&#xff1a; class Solution { public:long long findMaximumScore(vector<int>& nums) {if (nums.size() < 1) return 0LL;int n nums.size();vect…