Visual Studio 2022 C++ CLR 的艰难除 Bug

2023-05-16

请看下面一段代码:

运行结果:

  这是一个Button,要用到这段代码是因为字符串出了问题:

肯定是我写的类出问题了,便是我在控制台下测试是正常的。

  代码:

 运行结果:

 同样一行代码,在控制台运行的长度是13,在CLR上运行的是14

 

 14

 13

 后面怀疑是不是类型转换问题,我把所有构造函数加上explicit

 还是没发现问题,程序根本没有调用这些构造函数,难道问题在基类。

 把基类也加上explicit

 后来发现只是调用了基类构造函数

 百思不得其解,抓狂了:

  经过几小时后,最后发现我还定义了一个构造函数,粗心忘记了:

 查看代码,终于发现问题:

 正确版本是:

现在正确了:

结论:

语句:

_string s1 = L"button1_Click";

在CLR中,编译器先把 L"button1_Click" 转换为 System::String^,

然后调用构造函数 str_::str_(String^ sText) 再转换成  str_ ,

其中 _string 是我定义的宏:    #define _string  str_

够坑人吧!!!!!!!!

     这就是很多人宁愿用C而不用C++,这就是为什么出现 Java,C#的原因,除非

你有足够的耐心,足够的时间,足够的兴趣,否则少有C++乱七八糟的功能,例如:

多态,继承,多重继承,运算符重载,指针,这就是微软Visual Studio 2012 以后

没有再出现CLR的原因,因为实在是?????

memory_类定义代码0.1版 

/*******************************************************************************************
文件名							: memory_.h

作者								: 李锋

功能								:内存操作

创建时间							: 2016年7月6日

最后一次修改时间					:  2016年7月23日
********************************************************************************************/

#ifndef _MEMORY__H_
#define _MEMORY__H_

#include"macro_.h"
#include <assert.h>

_LF_BEGIN_

 
 
//内存操作类
class  memory_
{
public:
	//全局内存对象计数器
	static  __int64  _obj_used;
	static __int64  _mem_used;

	//充许最大内存数量
	static size_t _memory_allow_max;

public:
	 memory_();
	~ memory_();

	static inline size_t allow_max(){	return   _memory_allow_max;	}

	//内存使用量,字节
	static inline __int64 mem_used() { return    _mem_used;}

	//对象使用量
	static inline __int64 obj_used() { return    _obj_used; }


public:
	//分配内存,给对象分配内存不能用C语言的malloc函数
	template<typename T> static   T   * memNew(size_t  nCount, bool bDefaultValue = false)
	{
		//std::cout << "分配对象为:" << "T" << typeid(T).name() << "\t 个数nCount="<< nCount << "\n";
		 
		if (nCount == 0)  return null;
		 
		if (nCount > _memory_allow_max){	throw "超出最大充许申请的对象数";return 0;	}

		 
		_obj_used += nCount;
		_mem_used = _mem_used + sizeof(T) * nCount;
		
		if (bDefaultValue)
		{
			return memory_::memset_<T>(new T[nCount], nCount, T());
		}
		else		
		{				
			return  new T[nCount];
		}		
	}





	//释放内存
	template<typename T> static   void memDelete(T *pMemory, size_t  nCount)
	{ 
		_obj_used -= nCount;
		_mem_used -= sizeof(T) * nCount;
		delete[] pMemory;	
		pMemory = null;
	}



	//设置值
	template<typename T> static   T   *memset_(T *pMem,const size_t  nCount,  const T &rDefaultValue)
	{		 
#ifdef _LF_DEBUG_
		assert(pMem);
#endif
		for (size_t n = 0; n < nCount; ++n)
			*(pMem + n) = rDefaultValue;		
		return pMem;
	}


	 
	//每一个类必须写 T& T::operator=(const T &rhs)
	/// <summary>
	///  
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="pDestination"></param>
	/// <param name="pSource"></param>
	/// <param name="nCount"></param>
	/// <returns></returns>
	/// 创建时间: ????-??-??      最后一次修改时间:2021-10-26
	template<typename T> static T *memcpy_(T *pDestination, const T *pSource, const size_t nCount)
	{	 		
#ifdef _LF_DEBUG_	

		assert(nCount != 0 && pDestination != null && pSource != null);		
#endif		
		for (size_t n = 0; n < nCount; ++n)
		{
			pDestination[n] = pSource[n];			
		}
		return pDestination;
	}

private:
 
 };



 /// <summary>
 /// 内存管理,内存自动释放
 /// </summary>
 /// <typeparam name="T"></typeparam>
 template<typename T>
 class mem
 {
 private:
	 size_t _nCount;
 public:
	 T* data;
	 size_t effectiveCount = 0;  //有效数据个数

	 const size_t& count() const { return _nCount; } 

	 mem(const size_t& nCount) {
		 _nCount = nCount;
		 data = memory_::memNew<T>(nCount, false);
	 }

	 ~mem() {
		 memory_::memDelete<T>(data, _nCount);
	 }
 };



_LF_END_


#endif //--------------------------------------------------------------------------- !_memory__H_

str_类定义代码0.1版 

str_.h

/*******************************************************************************************
文件名						: str_.h

功能							: 模拟std::string C# String Java.String

程序字体						: Consolas,11

作者							: 李锋

手机							: 13828778863

Email						: ruizhilf@139.com

创建时间						: 2016年07月06日

									------------------------------最后一次修改时间:2022年11月03日
***********************************************************************************************/


#ifndef _STR__H_
#define _STR__H_

#include <iostream>
#include "macro_.h"
#include "math_.h"


_LF_BEGIN_



#if _CLR_
using namespace System;
#endif


class str_  
{
private:
	char_*			_pData;							//指针,指向第一个元素
	size_t			_nLength;						//无素个数
	size_t          _nBuffer;						//剩余缓冲区大小
	size_t          _nDefaultBuffer = 15;			//每次分配内容多分配缺省缓冲区大小

public:
	static const size_t npos = -1;

public:
	//---------------------------------------------------------------------------------构造与析构


	str_();  //缺省构造,默认为15个字符的缓冲大小
	explicit str_(const char_& ch);
	str_(const str_& rhs);
	str_(const char_* pstr, const size_t& nBuffer = 0);   //拷贝构造,默认为0个字符的缺省缓冲
	explicit str_(const char_* pstr, const size_t& nStrLength, const size_t& nCopyStart, const size_t& nCopyLength, const size_t& nBuffer = 0);





#if _CLR_
	str_(String^ sText);
#endif

	~str_();


public://-----------------------------------------------------------------------------属性
 
	//元素总数
	inline const size_t length() const { return _nLength; }

	//缓冲数量
	inline size_t capacity()const { return _nBuffer; }

	//缺省缓冲数量
	inline size_t defaultBuffer() const { return _nDefaultBuffer; }

	//设置缺省缓冲数量
	inline void defaultBuffer(const size_t& nDefaultBuffer) { _nDefaultBuffer = nDefaultBuffer; }

	//是否为空
	inline bool isEmpty() { return _nLength == 0; }



public://-----------------------------------------------------------------------------运算符重载
	str_& operator=(const char_* pStr);
	str_& operator=(const str_& rhs);
	str_& operator+=(const str_& rhs);

	/// <summary>
	/// 如果不定义operator+=(const const char_* psz)
	/// str_  s; 
	///  s+=L"abc";  =>> tmp = str_(L"abc") => s += tmp;
	/// 编译器会把L"abc" 用构造函数转换成str_再用加,多了中间环节,缺少效率,
	/// 而用explicit禁止隐式转换时,又为很麻烦! 例如: str_ fun();  return L"abc"   编译不了。
	/// </summary>
	/// <param name="psz"></param>
	/// <returns></returns>
	str_& operator+=(const char_* psz);

	friend str_ operator + (const str_& sLeft, const str_& sRigth);
	friend str_ operator + (const str_& sLeft, const int& iRigth);
	friend bool operator > (const str_& sLeft, const str_& sRigth);
	friend bool operator < (const str_& sLeft, const str_& sRigth);
	friend bool operator == (const str_& sLeft, const str_& sRigth);
	friend bool operator == (const str_& sLeft, const char_* sRigth);

public:
	void setBuffer(const size_t& nBuffer);
	const char_* add(const char_* pData, const size_t nLength);

	inline  const char_* add(const char_* pStr) { return add(pStr, math_::strlen(pStr)); }
	inline  const str_& add(const str_& rs) { add(rs._pData, rs._nLength); return *this; }
	inline  const char_* add(const char_& aChar) { return add(&aChar, 1); }
	void initData(const size_t& nBuffer);
	void clearData();
	str_ intStrFillUp(int nCount = 4)const;

public:  //---------------------------------------------------------------全局表态
	static str_ keepSmallDigits(const double& dNumber, const size_t nDigitsCount);



public:
	inline const char_* c_str() const { return  _pData; }


public:

	//从nStart开始向后查找aTypeValue第一次出现在当前容器中的位置,失败时返回linearmemory_::npos
	inline size_t find_(const char_& aTypeValue, const size_t nStart = 0) const { return math_::find(_pData, _nLength, &aTypeValue, 1, nStart); }

	//从nStart开始向后查找长度为pFindLength的pFind数据第一次出现在当前容器中的位置,失败时返回linearmemory_::npos
	inline size_t find_(const char_* pFind, const size_t& nStart, const size_t& pFindLength) const { return math_::find(_pData, _nLength, pFind, pFindLength, nStart); }

	//从nStart开始向后查找aFindLLinearList第一次出现在当前容器中的位置,失败时返回linearmemory_::npos 
	size_t find_(const str_ &aFindLLinearList, const size_t& nStart = 0) const { return math_::find(_pData, _nLength, aFindLLinearList._pData, aFindLLinearList._nLength, nStart); }



	//从nStart开始向前查找aTypeValue第一次出现在当前容器中的位置,失败时返回linearmemory_::npos。
	inline size_t rfind_(const char_& aTypeValue, const size_t& nStart = npos) const { return math_::rfind(_pData, _nLength, &aTypeValue, 1, nStart); }

	//从nStart开始向前查找长度为pFindLength的pFind数据第一次出现在当前容器中的位置,失败时返回linearmemory_::npos
	inline size_t rfind_(const char_* pFind, const size_t& nStart, const size_t& pFindLength) const { return math_::rfind(_pData, _nLength, pFind, pFindLength, nStart); }

	//从nStart开始向前查找aFindLLinearList第一次出现在当前容器中位置,失败时返回linearmemory_::npos 
	inline size_t rfind_(const str_& aFindLLinearList, const size_t& nStart = npos) const { return math_::rfind(_pData, _nLength, aFindLLinearList._pData, aFindLLinearList._nLength, nStart); }




	//从nStart开始向后查找aTypeValue第一次出现的位置,失败时返回linearmemory_::npos
	inline size_t find_first_of_(const char_& aTypeValue, const size_t& nStart = 0) const { return math_::find_first_of(_pData, _nLength, &aTypeValue, 1, nStart); }

	//从nStart开始向后查找长度为pFindLength的pFind数据任一元素第一次出现的位置,失败时返回linearmemory_::npos
	inline size_t find_first_of_(const char_* pFind, const size_t& nStart, const size_t& pFindLength) const { return math_::find_first_of(_pData, _nLength, pFind, pFindLength, nStart); }

	//从nStart开始向后查找aFindLLinearList任一元素第一次出现的位置,失败时返回linearmemory_::npos 
	size_t find_first_of_(const str_& aFindLLinearList, const size_t& nStart = 0) const { return math_::find_first_of(_pData, _nLength, aFindLLinearList._pData, aFindLLinearList._nLength, nStart); }


	//从nStart开始向后查找aTypeValue第一次不出现的位置,失败时返回linearmemory_::npos
	inline size_t find_first_not_of_(const char_& aTypeValue, const size_t& nStart = 0) const { return math_::find_first_not_of(_pData, _nLength, &aTypeValue, 1, nStart); }

	//从nStart开始向后查找长度为pFindLength的pFind数据任一元素第一次不出现的位置,失败时返回linearmemory_::npos
	inline size_t find_first_not_of_(const char_* pFind, const size_t& nStart, const size_t& pFindLength) const { return math_::find_first_not_of(_pData, _nLength, pFind, pFindLength, nStart); }

	//从nStart开始向后查找aFindLLinearList任一元素第一次不出现的位置,失败时返回linearmemory_::npos 
	size_t find_first_not_of_(const str_& aFindLLinearList, const size_t& nStart = 0) const { return math_::find_first_not_of(_pData, _nLength, aFindLLinearList._pData, aFindLLinearList._nLength, nStart); }


	//从nStart开始向前查找aTypeValue第一次出现的位置,成功返回索引处,失败时返回linearmemory_::npos
	inline size_t find_last_of_(const char_& aTypeValue, const size_t& nStart = 0) const { return math_::find_last_of(_pData, _nLength, &aTypeValue, 1, nStart); }

	//从nStart开始向前查找pFind中元系第一次出现的位置,成功返回索引处,失败时返回linearmemory_::npos
	inline size_t find_last_of_(const char_* pFind, const size_t& nStart, const size_t& pFindLength) const { return math_::find_last_of(_pData, _nLength, pFind, pFindLength, nStart); }


	//从nStart开始向前(倒序)查找aFindLLinearList任一元素第一次出现的位置,找到返回索引处,失败时返回linearmemory_::npos
	size_t find_last_of_(const str_& aFindLLinearList, const size_t& nStart = 0) const { return math_::find_last_of(_pData, _nLength, aFindLLinearList._pData, aFindLLinearList._nLength, nStart); }



	//从nStart开始向前查找aTypeValue第一次不出现的位置,失败时返回linearmemory_::npos
	inline size_t find_last_not_of_(const char_& aTypeValue, const size_t& nStart = 0) const { return math_::find_last_not_of(_pData, _nLength, &aTypeValue, 1, nStart); }

	//从nStart开始向前查找长度为pFindLength的pFind数据任一元素第一次不出现的位置,失败时返回linearmemory_::npos
	inline size_t find_last_not_of_(const char_* pFind, const size_t& nStart, const size_t& pFindLength) const { return math_::find_last_not_of(_pData, _nLength, pFind, pFindLength, nStart); }

	//从nStart开始向前查找aFindLLinearList任一元素第一次不出现的位置,失败时返回linearmemory_::npos 
	size_t find_last_not_of_(const str_& aFindLLinearList, const size_t& nStart = 0) const { return math_::find_last_not_of(_pData, _nLength, aFindLLinearList._pData, aFindLLinearList._nLength, nStart); }

	 
	 

	//从nStart开始向后查找长度为pFindLength的pFind数据第一次出现在当前容器中的位置,失败时返回linearmemory_::npos
	//inline size_t find_(const char_* pFind, const size_t& nStart, const size_t& pFindLength) const { return math_::find(_pData, _nLength, pFind, pFindLength, nStart); }

	//从nStart开始向后查找字符c在当前字符串的位置
	inline size_t find(const char_& c, const size_t& nStart = 0) const { return find_(&c, nStart, 1); }

	//从nStart开始向后查找字符串s在当前串中的位置
	inline size_t find(const char_* pFindStr, const size_t& nStart = 0) const { return find_(pFindStr, nStart, math_::strlen(pFindStr)); }

	//从nStart开始向后查找字符串s中前nFindLength个字符在当前串中的位置
	inline size_t find(const char_* pFindStr, const size_t& nStart, const size_t& nFindLength) const { return find_(pFindStr, nStart, nFindLength); }

	//从pos开始向后查找字符串s在当前串中的位置
	inline size_t find(const str_& s, const size_t& nStart = 0) const { return find_(s, nStart); }


	//从nStart开始向前查找字符c在当前字符串的位置,从nStart开始从后向前查找字符c在当前串中的位置
	inline size_t rfind(char_ c, const size_t& nStart = npos) const { return rfind_(c, nStart); }

	//从nStart开始向前查找字符串pFindStr在当前字符串的位置,从nStart开始从后向前查找字符c在当前串中的位置
	inline size_t rfind(const char_* pFindStr, const size_t& nStart = npos) const { return rfind_(pFindStr, nStart, math_::strlen(pFindStr)); }

	//从nStart开始向前查找字符串pFindStr在当前字符串的位置,从nStart开始从后向前查找字符c在当前串中的位置
	inline size_t rfind(const char_* pFindStr, const size_t& nLength, const size_t& nStart = npos) const { return rfind_(pFindStr, nStart, nLength); }

	//从nStart开始向前查找字符串s在当前字符串的位置,从nStart开始从后向前查找字符c在当前串中的位置
	inline size_t rfind(const str_& s, const size_t& nStart = npos) const { return rfind_(s, nStart); }


	//从nStart开始向后查找字符c第一次出现的位置
	inline size_t find_first_of(char_ c, const size_t& nStart = 0) const { return find_first_of_(c, nStart); }
	size_t find_first_of(const char_* pStr, const size_t& nStart = 0) const { return find_first_of_(pStr, nStart, math_::strlen(pStr)); }
	size_t find_first_of(const char_* pStr, const size_t& nStart, const size_t& nFindLength) const { return find_first_of_(pStr, nStart, nFindLength); }
	size_t find_first_of(const str_& s, const size_t& nStart = 0) const { return find_first_of_(s, nStart); }


	//从nStart开始向后查找字符c第一次没有出现的位置
	inline size_t find_first_not_of(char_ c, const size_t& nStart = 0) const { return find_first_not_of_(c, nStart); }
	size_t find_first_not_of(const char_* pStr, const size_t& nStart = 0) const { return find_first_not_of_(pStr, nStart, math_::strlen(pStr)); }
	size_t find_first_not_of(const char_* pStr, const size_t& nStart, const size_t& nFindLength) const { return find_first_not_of_(pStr, nStart, nFindLength); }
	size_t find_first_not_of(const str_& s, const size_t& nStart = 0) const { return find_first_not_of_(s, nStart); }


	//从nStart开始向前查找字符c第一次出现的位置
	inline size_t find_last_of(const char_& c, const size_t& nStart = npos) const { return find_last_of_(c, nStart); }
	size_t find_last_of(const char_* pStr, const size_t& nStart = npos) const { return find_last_of_(pStr, nStart, math_::strlen(pStr)); }
	size_t find_last_of(const char_* pStr, const size_t& nStart, const size_t& nFindLength) const { return find_last_of_(pStr, nStart, nFindLength); }
	size_t find_last_of(const str_& s, const size_t& nStart = npos) const { return find_last_of_(s, nStart); }


	//从nStart开始向前查找字符c第一次没有出现的位置
	inline size_t find_last_not_of(char_ c, const size_t& nStart = npos) const { return find_last_not_of_(c, nStart); }
	size_t find_last_not_of(const char_* pStr, const size_t& nStart = npos) const { return find_last_not_of_(pStr, nStart, math_::strlen(pStr)); }
	size_t find_last_not_of(const char_* pStr, const size_t& nStart, const size_t& nFindLength) const { return find_last_not_of_(pStr, nStart, nFindLength); }
	size_t find_last_not_of(const str_& s, const size_t& nStart = npos) const { return find_last_not_of_(s, nStart); }

	//添加换行符
	inline void newline() { add('\n'); }
	//添加水平制表键
	inline void horizontalTab() { add('\t'); }
	//添加垂直制表键
	inline void verticalTab() { add('\v'); };
	//添加退格键
	inline void backspace() { add('\b'); }
	//添加回车键
	inline void carriageReturn() { add('\r'); }
	//添加进纸键
	inline void formfeed() { add('\f'); }
	//添加响铃符
	inline void alert() { add('\a'); }
	//添加反斜杠键
	inline void backslash() { add('\\'); }
	//添加问号
	inline void questionMark() { add('\?'); }
	//添加单引号
	inline void singleQuote() { add('\''); }
	//添加双引号
	inline void doubleQuote() { add('\"'); }

public://--------------------------------------------------------------------------------模似CSharp字符串String

	int csharp_indexOf(const char_& value, const int& startIndex, const int& count) const;
	int csharp_indexOf(const char_& value, const int& startIndex) const;
	int csharp_indexOf(const str_& value) const;
	int csharp_indexOf(const str_& value, const int& startIndex) const;
	int csharp_indexOf(const str_& value, const int& startIndex, const int& count) const;
	//int indexOf(const str_& value, StringComparison comparisonType) const;
	//int indexOf(const str_& value, const int& startIndex, StringComparison comparisonType) const;
	int csharp_indexOf(const char_& value) const;
	//int indexOf(const str_& value, const int&  startIndex, const int&  count, StringComparison comparisonType) const;
	//int indexOfAny(char[] anyOf, const int&  startIndex, const int&  count) const;     
	//int indexOfAny(char[] anyOf, const int&  startIndex) const;
	//int indexOfAny(char[] anyOf) const;
	str_ csharp_Substring(const int& startIndex, const int& length) const;
	str_ csharp_Substring(const int& startIndex)const;
	str_ csharp_Trim()const;
	str_ csharp_Trim(const char_& ch)const;
	str_ csharp_ToLower() const;
	int csharp_IndexOf(const str_& sSub)const;
	inline int csharp_Length()const { return _nLength; }


	//--------------------------------------------------------------------------------模似Java字符串String
	static str_  java_valueOf(const __int64& iNumber);
	static str_  java_valueOf(const int& iNumber);
	static str_  java_valueOf(const size_t& iNumber);


	//---------------------------------------------------------------------------------自己添加的功能函数

	static str_  copyFrom(const char_* pStr, size_t nStrLength, size_t nCopyStart, size_t nCopyLength);


};


#ifdef UNICODE
std::wistream& operator >> (std::wistream& os, str_& aString);
std::wostream& operator<<(std::wostream& os, const str_& aString);
#else
std::istream& operator >> (std::istream& os, str_& aString);
std::ostream& operator<<(std::ostream& os, const str_& aString);
#endif




_LF_END_

#endif

 str_.cpp

#include "str_.h"
#include "std_.h"
#include "global_c_.h"
#include "memory_.h"

_LF_BEGIN_

//#define _STR__DEBUG_

//------------------------------------------------------------------------------功能函数

//添回字符串,充许pData == null 或者 nLength = 0
const char_* str_::add(const char_* pData, const size_t nLength)
{
#ifdef  _STR__DEBUG_
	std::wcout << L"const char_ *str_::add(const char_ *pData, const size_t nLength)\n";
#endif //  _STR__DEBUG_
 

	if (nLength == 0 || pData == null) { return _pData; }

	if (_nBuffer >= nLength)
	{
		memory_::memcpy_<char_>(_pData + _nLength, pData, nLength);
		_nBuffer -= nLength;
		_nLength += nLength;
	}
	else
	{


		char_* pNew = memory_::memNew<char_>(_nDefaultBuffer + _nLength + nLength + 1, false);

		if (_nLength > 0)
			memory_::memcpy_<char_>(pNew, _pData, _nLength);    //拷贝原来的数据

		memory_::memcpy_<char_>(pNew + _nLength, pData, nLength); //拷贝新的内存
		memory_::memDelete<char_>(_pData, _nLength + _nBuffer + 1);  //释放内存
		_nLength += nLength;
		_nBuffer = _nDefaultBuffer;
		_pData = pNew;
	}

	_pData[_nLength] = 0;

	return this->_pData;
}



/// <summary>
/// 初始化数据,并设置缓冲区大小
/// </summary>
/// <param name="nBuffer"></param>
/// 创建时间: ????-??-??      最后一次修改时间:2022-10-07
void str_::initData(const size_t& nBuffer)
{
#ifdef  _STR__DEBUG_

	std::wcout << L"void str_::initData(const size_t& nDefaultBuffer)\n";

#endif //  _STR__DEBUG_

	_pData = memory_::memNew<char_>(nBuffer + 1, false);

	_pData[0] = 0;
	_nLength = 0;
	_nBuffer = nBuffer;	
}





//设为空字符串
void str_::clearData()
{
#ifdef  _STR__DEBUG_
	std::wcout << L"void str_::clearData()";
#endif //  _STR__DEBUG_

	//不充出现null指针
	_nBuffer = _nLength + _nBuffer;
	_nLength = 0;

	_pData[0] = 0;
}


/// <summary>
/// 设置缓冲区
/// </summary>
/// <param name="nBuffer"></param>
/// 创建时间: 2022-10-07      最后一次修改时间:2022-10-07
void str_::setBuffer(const size_t& nBuffer)
{
	//std::cout << "virtual void linearmemory_<T>::setBuffer(const size_t& nBuffer)" << "\n";

	if (_nBuffer == nBuffer)
		return;

	if (nBuffer == 0) return;


	char_* pNew = memory_::memNew<char_>(_nLength + nBuffer, false); //分配新内存

	if (_nLength > 0) { memory_::memcpy_(pNew, _pData, _nLength); }  //拷贝旧数据

	memory_::memDelete<char_>(_pData, _nLength + _nBuffer + 1);  //空字符点一位

	_pData = pNew;
	_nBuffer = nBuffer;
}


/// <summary>
/// 补位4,用0替代,返回一个副本,例如:
/// 1 => 0001
/// 10 => 0010
/// 99999 => 9999
/// </summary>
/// <param name="nCount"></param>
/// <returns></returns>
str_ str_::intStrFillUp(int nCount) const{

	if (nCount <= 0)  return L"";
	 
	if (nCount > _nLength)
	{
		str_ sResult(L"", nCount);

		for (int i = 1; i <= nCount - _nLength; ++i) {		 

			sResult.add(L'0');
		}

		for (int i = 0; i < _nLength; ++i) {

			sResult.add(_pData[i]);
		}

		return sResult;
	}
	else
	{
		return this->copyFrom(_pData, _nLength, _nLength - nCount, nCount);
	}
}



//---------------------------------------------------------------------------------构造与析构


/// <summary>
/// 默认为15个字符的缓冲大小
/// </summary>
str_::str_()
{
#ifdef  _STR__DEBUG_
	std::wcout << L"str_::str_()";
#endif //  _STR__DEBUG_

	initData(15);
}


str_::str_(const char_& ch)
{
#ifdef  _STR__DEBUG_
	std::wcout << L"str_::str_(const char_& ch)";
#endif //  _STR__DEBUG_
	initData(1);
	_pData[0] = ch;
	_pData[1] = 0;
	_nBuffer = 0;
	_nLength = 1;
}




str_::str_(const str_& rhs)
{
#ifdef  _STR__DEBUG_
	std::wcout << L"str_::str_(const str_ &rhs)";
#endif //  _STR__DEBUG_

	if (rhs._nLength == 0) { initData(0);}
	else{
		initData(rhs._nLength + _nDefaultBuffer);
		add(rhs._pData, rhs._nLength);
	}
}



/// <summary>
/// 
/// </summary>
/// <param name="pStr"></param>
/// <param name="nBuffer"></param>
str_::str_(const char_* pStr, const size_t& nBuffer)
{
	// 定义: int str_::csharp_IndexOf(const str_& sSub) const
	// str_ s = L"abc";
	// s.csharp_IndexOf( null ); 此时编译时会把 null 转换为 str_,用的就是这个构造涵数。 

#ifdef  _STR__DEBUG_

	std::wcout << L"str_::str_(const char_ *pStr,const size_t nBuffer)\n";

	//System::Windows::Forms::MessageBox::Show(L"str_::str_(const char_* pStr, const size_t& nBuffer)");

#endif //  _STR__DEBUG_

	//错不能用这个,当str_ aStr = null 时,先调用str_::strlen(pStr)
	//str_::str_(const char_ *pStr) : linearmemory_<char_>(pStr,str_::strlen(pStr))
	//并且构造函数中的子类虚函数是无效的,例如:当构造linearmemory_时,str_还未构造出来

	if (pStr != null)
	{
		size_t nLength = math_::strlen(pStr); 

		initData(nLength + nBuffer);
		this->add(pStr, nLength);
	}else
	{
		initData(nBuffer);
	}
}



/// <summary>
/// 拷贝构造函数
/// </summary>
/// <param name="pstr">要拷贝的字符串</param>
/// <param name="nStrLength">要拷贝的字符串长度</param>
/// <param name="nCopyStart">从那里开始拷贝,索引从零开始</param>
/// <param name="nCopyLength">要拷贝的长度</param>
/// <param name="nBuffer">字符串区缓冲区长度</param>
/// 创建时间: ????-??-??      最后一次修改时间:2021-11-02
str_::str_(const char_* pstr, const size_t& nStrLength, const size_t& nCopyStart, const size_t& nCopyLength, const size_t& nBuffer)
{

#ifdef  _STR__DEBUG_
	std::wcout << L"str_::str_(const char_* pstr, const size_t& nCopyStart, const size_t& nCopyLength, const size_t nBuffer)\n";
	//System::Windows::Forms::MessageBox::Show(L"const char_* pstr, const size_t& nStrLength, const size_t& nCopyStart, const size_t& nCopyLength, const size_t& nBuffer");
#endif //  _STR__DEBUG_

	if (pstr == null || nCopyLength == 0 || nCopyStart >= nStrLength)
	{
		initData(nBuffer);
		return;
	}

	if (nCopyLength + nCopyStart <= nStrLength)
	{
		_nLength = nCopyLength;
	}
	else
	{
		_nLength = nStrLength - nCopyStart;
	}




	_nDefaultBuffer = 0;
	_nBuffer = nBuffer;
	_pData = memory_::memNew<char_>(_nLength + _nBuffer + 1, false);
	memory_::memcpy_(_pData, pstr + nCopyStart, _nLength);


	_pData[_nLength] = 0;
}

#if _CLR_

str_::str_(String^ sText)
{
	//System::Windows::Forms::MessageBox::Show(L"str_::str_(String^ sText)");

	if (sText->Length > 0)
	{
		int nLength = sText->Length;

		initData(nLength + _nDefaultBuffer);

		for (int i = 0; i < nLength; ++i) {
			_pData[i] = sText[i];
		}

		_nLength = nLength;
		_nBuffer = _nDefaultBuffer;
		_pData[nLength] = 0;
	}
	else
	{
		initData(0);
	}
}

#endif

str_::~str_()
{

#ifdef  _STR__DEBUG_
	std::wcout << L"str_::~str_()\n";
	//System::Windows::Forms::MessageBox::Show(L"str_::~str_()");
#endif //  _STR__DEBUG_

	//编译器先调用str_::~str_(),然后再调用:linearmemory_<char_>::~LinearList()
	++_nLength;
}

//--------------------------------------------------------------------------------模似CSharp字符串String


//
// 摘要:
//     报告指定字符在此实例中的第一个匹配项的从零开始的索引。 搜索从指定字符位置开始,并检查指定数量的字符位置。
//
// 参数:
//   value:
//     要查找的 Unicode 字符。
//
//   startIndex:
//     搜索起始位置。
//
//   count:
//     要检查的字符位置数。
//
// 返回结果:
//     如果找到该字符,则为从字符串的起始位置开始的 value 从零开始的索引位置;否则为 -1。
//
// 异常:
//   T:System.ArgumentOutOfRangeException:
//     count 或 startIndex 为负数。 - 或 - startIndex 大于此字符串的长度。 - 或 - count 大于此字符串的长度减 startIndex。
/// <summary>
/// 
/// </summary>
/// <param name="value"></param>
/// <param name="startIndex"></param>
/// <param name="count"></param>
/// <returns></returns>
/// 创建时间: 2021-10-28      最后一次修改时间:2021-10-28    优化测式: 否
int str_::csharp_indexOf(const char_& value, const int& startIndex, const int& count)const
{
	//return math_::find<char_>(&value, 1, _pData, count, startIndex);

	return -1;
}



//
// 摘要:
//     报告指定 Unicode 字符在此字符串中的第一个匹配项的从零开始的索引。 该搜索从指定字符位置开始。
//
// 参数:
//   value:
//     要查找的 Unicode 字符。
//
//   startIndex:
//     搜索起始位置。
//
// 返回结果:
//     如果找到该字符,则为从字符串的起始位置开始的 value 从零开始的索引位置;否则为 -1。
//
// 异常:
//   T:System.ArgumentOutOfRangeException:
//     startIndex 小于 0(零)或大于此字符串的长度。
int str_::csharp_indexOf(const char_& value, const int& startIndex)const
{
	return csharp_indexOf(value, startIndex, _nLength - startIndex - 1);
}



//
// 摘要:
//     报告指定字符串在此实例中的第一个匹配项的从零开始的索引。
//
// 参数:
//   value:
//     要搜寻的字符串。
//
// 返回结果:
//     如果找到该字符串,则为 value 的从零开始的索引位置;如果未找到该字符串,则为 -1。 如果 value 为 System.String.Empty,则返回值为
//     0。
//
// 异常:
//   T:System.ArgumentNullException:
//     value 为 null。
int str_::csharp_indexOf(const str_& value)const
{

	return find(value);
}



//
// 摘要:
//     报告指定字符串在此实例中的第一个匹配项的从零开始的索引。 该搜索从指定字符位置开始。
//
// 参数:
//   value:
//     要搜寻的字符串。
//
//   startIndex:
//     搜索起始位置。
//
// 返回结果:
//     如果找到该字符串,则为从当前实例的起始位置开始的从零开始的 value 的索引位置;否则为 -1。 如果 value 为 System.String.Empty,则返回值为
//     startIndex。
//
// 异常:
//   T:System.ArgumentNullException:
//     value 为 null。
//
//   T:System.ArgumentOutOfRangeException:
//     startIndex 小于 0(零)或大于此字符串的长度。
int str_::csharp_indexOf(const str_& value, const int& startIndex)const
{
	return find(value, startIndex);

}



//
// 摘要:
//     报告指定字符串在此实例中的第一个匹配项的从零开始的索引。 搜索从指定字符位置开始,并检查指定数量的字符位置。
//
// 参数:
//   value:
//     要搜寻的字符串。
//
//   startIndex:
//     搜索起始位置。
//
//   count:
//     要检查的字符位置数。
//
// 返回结果:
//     如果找到该字符串,则为从当前实例的起始位置开始的从零开始的 value 的索引位置;否则为 -1。 如果 value 为 System.String.Empty,则返回值为
//     startIndex。
//
// 异常:
//   T:System.ArgumentNullException:
//     value 为 null。
//
//   T:System.ArgumentOutOfRangeException:
//     count 或 startIndex 为负数。 - 或 - startIndex 大于此字符串的长度。 - 或 - count 大于此字符串的长度减 startIndex。
int str_::csharp_indexOf(const str_& value, const int& startIndex, const int& count)const
{
	assert(startIndex + count <= _nLength);

	return -1;
}



//
// 摘要:
//     报告指定的字符串在当前 System.String 对象中的第一个匹配项的从零开始的索引。 一个参数指定要用于指定字符串的搜索类型。
//
// 参数:
//   value:
//     要搜寻的字符串。
//
//   comparisonType:
//     指定搜索规则的枚举值之一。
//
// 返回结果:
//     如果找到该字符串,则为 value 参数的索引位置;如果未找到该字符串,则为 -1。 如果 value 为 System.String.Empty,则返回值为
//     0。
//
// 异常:
//   T:System.ArgumentNullException:
//     value 为 null。
//
//   T:System.ArgumentException:
//     comparisonType 不是有效的 System.StringComparison 值。
//int indexOf(String value, StringComparison comparisonType);



//
// 摘要:
//     报告指定的字符串在当前 System.String 对象中的第一个匹配项的从零开始的索引。 参数指定当前字符串中的起始搜索位置以及用于指定字符串的搜索类型。
//
// 参数:
//   value:
//     要搜寻的字符串。
//
//   startIndex:
//     搜索起始位置。
//
//   comparisonType:
//     指定搜索规则的枚举值之一。
//
// 返回结果:
//     如果找到该字符串,则为从当前实例的起始位置开始的从零开始的 value 参数索引位置;否则为 -1。 如果 value 为 System.String.Empty,则返回值为
//     startIndex。
//
// 异常:
//   T:System.ArgumentNullException:
//     value 为 null。
//
//   T:System.ArgumentOutOfRangeException:
//     startIndex 小于 0(零)或大于此字符串的长度。
//
//   T:System.ArgumentException:
//     comparisonType 不是有效的 System.StringComparison 值。
// int indexOf(String value, int startIndex, StringComparison comparisonType);



//
// 摘要:
//     报告指定 Unicode 字符在此字符串中的第一个匹配项的从零开始的索引。
//
// 参数:
//   value:
//     要查找的 Unicode 字符。
//
// 返回结果:
//     如果找到该字符,则为 value 的从零开始的索引位置;如果未找到,则为 -1。
int str_::csharp_indexOf(const char_& value)const
{
	return -1;
}


//
// 摘要:
//     报告指定的字符串在当前 System.String 对象中的第一个匹配项的从零开始的索引。 参数指定当前字符串中的起始搜索位置、要搜索的当前字符串中的字符数量,以及要用于指定字符串的搜索类型。
//
// 参数:
//   value:
//     要搜寻的字符串。
//
//   startIndex:
//     搜索起始位置。
//
//   count:
//     要检查的字符位置数。
//
//   comparisonType:
//     指定搜索规则的枚举值之一。
//
// 返回结果:
//     如果找到该字符串,则为从当前实例的起始位置开始的从零开始的 value 参数索引位置;否则为 -1。 如果 value 为 System.String.Empty,则返回值为
//     startIndex。
//
// 异常:
//   T:System.ArgumentNullException:
//     value 为 null。
//
//   T:System.ArgumentOutOfRangeException:
//     count 或 startIndex 为负数。 - 或 - startIndex 大于此实例的长度。 - 或 - count 大于此字符串的长度减 startIndex。
//
//   T:System.ArgumentException:
//     comparisonType 不是有效的 System.StringComparison 值。
//int indexOf(String value, int startIndex, int count, StringComparison comparisonType);



//
// 摘要:
//     报告指定 Unicode 字符数组中的任意字符在此实例中第一个匹配项的从零开始的索引。 搜索从指定字符位置开始,并检查指定数量的字符位置。
//
// 参数:
//   anyOf:
//     Unicode 字符数组,包含一个或多个要查找的字符。
//
//   startIndex:
//     搜索起始位置。
//
//   count:
//     要检查的字符位置数。
//
// 返回结果:
//     在此实例中第一次找到 anyOf 中的任意字符的索引位置(从零开始);如果未找到 anyOf 中的字符,则为 -1。
//
// 异常:
//   T:System.ArgumentNullException:
//     anyOf 为 null。
//
//   T:System.ArgumentOutOfRangeException:
//     count 或 startIndex 为负数。 - 或 - count + startIndex 大于此实例中的字符数。    
//int indexOfAny(char[] anyOf, int startIndex, int count);




//
// 摘要:
//     报告指定 Unicode 字符数组中的任意字符在此实例中第一个匹配项的从零开始的索引。 该搜索从指定字符位置开始。
//
// 参数:
//   anyOf:
//     Unicode 字符数组,包含一个或多个要查找的字符。
//
//   startIndex:
//     搜索起始位置。
//
// 返回结果:
//     在此实例中第一次找到 anyOf 中的任意字符的索引位置(从零开始);如果未找到 anyOf 中的字符,则为 -1。
//
// 异常:
//   T:System.ArgumentNullException:
//     anyOf 为 null。
//
//   T:System.ArgumentOutOfRangeException:
//     startIndex 为负数。 - 或 - startIndex 大于此实例中的字符数。
//int indexOfAny(char[] anyOf, int startIndex);


//
// 摘要:
//     报告指定 Unicode 字符数组中的任意字符在此实例中第一个匹配项的从零开始的索引。
//
// 参数:
//   anyOf:
//     Unicode 字符数组,包含一个或多个要查找的字符。
//
// 返回结果:
//     在此实例中第一次找到 anyOf 中的任意字符的索引位置(从零开始);如果未找到 anyOf 中的字符,则为 -1。
//
// 异常:
//   T:System.ArgumentNullException:
//     anyOf 为 null。
//int indexOfAny(char[] anyOf);




//
// 摘要:
//     从此实例检索子字符串。 子字符串从指定的字符位置开始且具有指定的长度。
//
// 参数:
//   startIndex:
//     此实例中子字符串的起始字符位置(从零开始)。
//
//   length:
//     子字符串中的字符数。
//
// 返回结果:
//     与此实例中在 length 处开头、长度为 startIndex 的子字符串等效的一个字符串;如果 System.String.Empty 等于此实例的长度且
//     startIndex 为零,则为 length。
//
// 异常:
//   T:System.ArgumentOutOfRangeException:
//     startIndex 加 length 指示不在此实例内的位置。 - 或 - startIndex 或 length 小于零。
str_ str_::csharp_Substring(const int& startIndex, const int& length)const
{
	return str_(_pData, _nLength, startIndex, length);
}


//
// 摘要:
//     从此实例检索子字符串。 子字符串在指定的字符位置开始并一直到该字符串的末尾。
//
// 参数:
//   startIndex:
//     此实例中子字符串的起始字符位置(从零开始)。
//
// 返回结果:
//     与此实例中在 startIndex 处开头的子字符串等效的一个字符串;如果 System.String.Empty 等于此实例的长度,则为 startIndex。
//
// 异常:
//   T:System.ArgumentOutOfRangeException:
//     startIndex 小于零或大于此实例的长度。
str_ str_::csharp_Substring(const int& startIndex) const
{
	return str_(_pData, this->_nLength, startIndex, _nLength);
}




/// <summary>
/// 返回除去两边的空格和控制字符
/// </summary>
/// <returns></returns>
/// 创建时间:  2022-10-06  最后一次修改时间:  2022-10-06 已测试
str_ str_::csharp_Trim() const
{
	int nStart = 0;  int nEnd = 0;
	bool bFind = false;

	for (nStart = 0; nStart < _nLength; ++nStart)
	{
		char_ c = _pData[nStart];

		if (!std_::iscntrl_(c) && c != ' ') { bFind = true;  break; }
	}

	//if (nStart == _nLength - 1) return  _string();   //错,当字符是 1 个是时,任何情况  nStart == 0 成立

	if (nStart == _nLength - 1)
	{
		if (bFind) {
			return *this;
		}
		else {
			return  str_();
		}
	}


	bFind = false;

	for (nEnd = _nLength - 1; nEnd >= nStart; --nEnd)
	{
		char_ c = _pData[nEnd];

		if (!std_::iscntrl_(c) && c != ' ') { break; }
	}

	int nCopyLength = nEnd - nStart + 1;

	if (nCopyLength <= 0) return  str_();


	return csharp_Substring(nStart, nCopyLength);
}


/// <summary>
/// 除去两边的字符 ch
/// </summary>
/// <param name="ch"></param>
/// <returns></returns>
/// 创建时间:  2022-10-06  最后一次修改时间:  2022-10-06
str_ str_::csharp_Trim(const char_& ch) const
{

	int nStart = 0;  int nEnd = 0;
	bool bFind = false;


	for (nStart = 0; nStart < _nLength; ++nStart)
	{
		if (_pData[nStart] != ch) { break; }
	}

	//if (nStart == _nLength - 1) return  _string();   //错,当字符是 1 个是时,任何情况  nStart == 0 成立

	if (nStart == _nLength - 1)
	{
		if (bFind) {
			return *this;
		}
		else {
			return  str_();
		}
	}


	for (nEnd = _nLength - 1; nEnd >= 0; --nEnd)
	{
		if (_pData[nEnd] != ch) { break; }
	}

	int nCopyLength = nEnd - nStart + 1;

	if (nCopyLength <= 0) return  str_();


	return csharp_Substring(nStart, nCopyLength);
}


/// <summary>
/// 返回副本
/// </summary>
/// <returns></returns>
/// 创建时间:  2022-10-06  最后一次修改时间:  2022-10-06
str_ str_::csharp_ToLower() const
{
	str_ sResult(L"", _nLength + 1);


	for (int i = 0; i < _nLength; ++i) { sResult._pData[i] = std_::tolower_(_pData[i]); }

	sResult._nBuffer = 0;
	sResult._nLength = _nLength;
	sResult._pData[_nLength] = 0;

	return sResult;
}


/// <summary>
/// 
/// </summary>
/// <param name="sSub"></param>
/// <returns></returns>
/// 创建时间:  2022-10-06  最后一次修改时间:  2022-10-06   已测试 
int str_::csharp_IndexOf(const str_& sSub) const
{
	if (_nLength == 0 || sSub._nLength == 0) return -1;

	const int nEnd = _nLength - sSub._nLength;

	if (nEnd < 0) return -1;

	for (int i = 0; i <= nEnd; ++i) {

		bool bFind = true;

		for (int j = 0; j < sSub._nLength; ++j)
		{
			if (_pData[i + j] != sSub._pData[j])
			{
				bFind = false;
				break;
			}
		}

		if (bFind) return i;
	}

	return -1;
}





/// <summary>
/// 
/// </summary>
/// <param name="pStrin"></param>
/// <param name="nStart"></param>
/// <param name="nEnd"></param>
/// <returns></returns>
/// 创建时间: 2021-10-04      最后一次修改时间:2021-10-04
str_ str_::copyFrom(const char_* pStr, size_t nStrLength, size_t nCopyStart, size_t nCopyLength)
{
	return str_(pStr, nStrLength, nCopyStart, nCopyLength);
}



/// <summary>
/// 
/// </summary>
/// <param name="nValue"></param>
/// <returns></returns>
/// 创建时间: 2021-10-04      最后一次修改时间:2021-10-04
str_ str_::java_valueOf(const __int64& iNumber)
{
	mem<char_> m(50);

	int nLength = 0;

	math_::intToStr(iNumber, m.data, &m.effectiveCount);


	return str_::copyFrom(m.data, m.effectiveCount, 0, m.effectiveCount);

}


str_ str_::java_valueOf(const int& iNumber)
{
	return str_::java_valueOf((__int64)iNumber);
}

str_ str_::java_valueOf(const size_t& iNumber)
{
	return str_::java_valueOf((__int64)iNumber);
}





//-------------------------------------------------------------------------------------------------运算符串重载

str_& str_::operator=(const char_* pStr)
{
#ifdef  _STR__DEBUG_
	std::wcout << L"str_& str_::operator=(const char_ *pStr)\n";
#endif //  _STR__DEBUG_

#ifdef _LF_DEBUG_
	assert(pStr != null);
#endif
	if (_pData != pStr)
	{
		clearData();
		add(pStr);
	}
	return *this;
}



//str_ s1,s2;
// s1 = s2;        //此时设用这个函数,如果没写这个函数,
//                       则调用基类linearmemory_<T>& linearmemory_<T>::operator=(const linearmemory_<T> &rhs)
str_& str_::operator=(const str_& rhs)
{
#ifdef  _STR__DEBUG_
	std::wcout << L"str_& str_::operator=(const str_ &rhs)\n";
#endif //  _STR__DEBUG_

	if (&rhs != this)
	{
		clearData();
		if (rhs._nLength > 0)
			add(rhs.c_str(), rhs._nLength);
	}
	return *this;
}


str_& str_::operator+=(const str_& rhs)
{
#ifdef  _STR__DEBUG_
	std::wcout << L"str_& str_::operator+=(const str_& rhs)\n";
#endif //  _STR__DEBUG_

	add(rhs.c_str(), rhs._nLength);

	return *this;
}


str_& str_::operator+=(const char_* psz)
{

	add(psz);

	return *this;
}

str_ operator + (const str_& sLeft, const str_& sRight)
{
#ifdef  _STR__DEBUG_
	std::wcout << L"str_ operator + (const str_ & sLeft, const str_ & sRight)\n";
#endif //  _STR__DEBUG_

	str_ sResult(sLeft.c_str(), sRight._nLength + 10);
	sResult.add(sRight.c_str(), sRight._nLength);
	return sResult;
}

str_ operator+(const str_& sLeft, const int& iRigth)
{
#ifdef  _STR__DEBUG_
	std::wcout << L"str_ operator+(const str_& sLeft, const int& iRigth)\n";
#endif //  _STR__DEBUG_

	str_ sResult(sLeft.c_str(), 15);
	sResult.add(str_::java_valueOf(iRigth));
	return sResult;
}


bool operator > (const str_& sLeft, const str_& sRigth)
{
#ifdef  _STR__DEBUG_
	std::wcout << L"bool operator > (const str_& sLeft, const str_& sRigth)\n";
#endif //  _STR__DEBUG_

	return math_::strcmp(sLeft.c_str(), sRigth.c_str()) > 0;

}


bool operator < (const str_& sLeft, const str_& sRigth)
{
#ifdef  _STR__DEBUG_
	std::wcout << L"operator < (const str_& sLeft, const str_& sRigth)\n";
#endif //  _STR__DEBUG_

	return math_::strcmp(sLeft.c_str(), sRigth.c_str()) < 0;
}


bool operator == (const str_& sLeft, const str_& sRigth)
{
#ifdef  _STR__DEBUG_
	lcout << L"bool operator == (const str_& sLeft, const str_& sRigth)\n";
#endif //  _STR__DEBUG_


	if (sLeft._nLength != sRigth._nLength)
		return false;

	return math_::strcmp(sLeft.c_str(), sRigth.c_str()) == 0;
}


/// <summary>
/// 
/// </summary>
/// <param name="sLeft"></param>
/// <param name="sRigth"></param>
/// <returns></returns>
/// 创建时间: 2021-10-27      最后一次修改时间:2021-10-27
bool operator == (const str_& sLeft, const char_* sRigth)
{
#ifdef  _STR__DEBUG_
	std::wcout << L"bool operator == (const str_& sLeft, const char_* sRigth)\n";
#endif //  _STR__DEBUG_

	if (sRigth == null)
		return false;

	return math_::strcmp(sLeft.c_str(), sRigth) == 0;
}


/// <summary>
/// 保留小数位,四舍五入
/// </summary>
/// <param name="dNumber">保留小数位的数字</param>
/// <param name="nDigitsCount">保留小数的位数</param>
/// <returns></returns>
/// 创建时间: ????-??-??      最后一次修改时间:2021-11-02
str_ str_::keepSmallDigits(const double& dNumber, const size_t nDigitsCount)
{
	assert(nDigitsCount < 50);

	str_ sResult;
	sResult.setBuffer(50);

	char_ str[50];

	__int64 iNumber = dNumber;


	//取整数部分
	sResult.add(math_::intToStr(iNumber, str));

	if (nDigitsCount == 0)
		return sResult;
	else
	{

#ifdef UNICODE
		sResult.add(L".");
#else
		sResult.add(".");
#endif // UNICODE

		iNumber = (dNumber - iNumber) * math_::pow(10, nDigitsCount + 1); //取小数部份+1位

		//四舍五入
		if (math_::digitsOf(iNumber, 1) >= 5)
			iNumber = (iNumber / 10 + 1) * 10;

		iNumber = iNumber / 10;


		if (iNumber == 0)  //小数部分==0
		{
			for (size_t n = 0; n < nDigitsCount; ++n)
			{
#ifdef UNICODE
				sResult.add(L'0');
#else
				sResult.add('0');
#endif
			}
		}
		else
		{
			sResult.add(math_::intToStr(iNumber, str));
		}
	}

	return sResult;
}



#ifdef UNICODE


std::wistream& operator >> (std::wistream& os, str_& aString)
{
	char_ str[200];
	//os >> str;
	aString = str;
	return os;
}



std::wostream& operator<<(std::wostream& os, const str_& aString)
{
	os << aString.c_str();

	return os;
}

#else

std::istream& operator >> (std::istream& os, str_& aString)
{
	char_ str[200];
	//os >> str;
	aString = str;
	return os;
}



std::ostream& operator<<(std::ostream& os, const str_& aString)
{
	os << aString.c_str();

	return os;
}

#endif


_LF_END_

   linearmemory_.h  没什么用。

/*******************************************************************************************
文件名						: linearmemory_.h

作者							: 李锋

功能							: 线性表

创建时间						: 2016年07月16日

最后一次修改时间				:  2016年09月26日
********************************************************************************************/
#ifndef _LINEARMEMORY__H_  
#define _LINEARMEMORY__H_
#include<initializer_list>
#include "math_.h"
#include "memory_.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时该线性表称为空表。

**************************************************************************************************************/


//linearmemory_相当于std::vector,不限于线性表。
template<typename T>
class linearmemory_  :  public object_
{
protected:
	T*				_pData;							//指针,指向第一个元素
	size_t			_nLength;						//无素个数
	size_t          _nBuffer;						//空元素长度
	size_t          _nDefaultBuffer;				//缺省缓冲数量


public:
	static const size_t npos = -1;

	//-----------------------------------------------------------------------------------------------------------构造与析构函数
public:
	//阻止不应该允许的经过转换构造函数进行的隐式转换的发生,例如:linearmemory_<int> linearList = 5;
	explicit linearmemory_(const size_t nDefaultBuffer = 0);

	explicit linearmemory_(const T* pType, const size_t nCount, const size_t nDefaultBuffer = 10);
	explicit linearmemory_(const linearmemory_& rhs);


	//linearmemory_<_char> *ps = new LString("abc");  delete ps; 
	//如果linearmemory_的析构函数不用virtual,则上属语句LString的虚拟函数不会被调用
	//虚析构函数的作用是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
	//	当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器
	//会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一
	//个类被用来作为基类的时候,才把析构函数写成虚函数。
	virtual ~linearmemory_();


	/*
	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的构造函数如:
	*/
#if _MSC_VER
	linearmemory_(std::initializer_list<T> aList);
#endif
	//-------------------------------------------------------------------------------------------------------------操作符重载
public:
	linearmemory_& operator=(const linearmemory_& rhs);

	//重载的下标操作符
	T& operator[](const size_t& nIndex)const;

	bool operator==(const linearmemory_& rhs) const;

	bool operator!=(const linearmemory_& rhs) const;

	/*
	//模板类的友元函数,这里的的T跟T,是独立于类linearmemory_<T>的
	template<typename T>
	friend bool operator== (const linearmemory_<T>& lhs, const linearmemory_<T>& rhs);

	template<typename T>
	friend bool operator!= (const linearmemory_<T>& lhs, const linearmemory_<T>& rhs);
	*/
public:
	//-----------------------------------------------------------------------------------------------------属性
	//元素总数
	inline const size_t length() const { return _nLength; }

	//缓冲数量
	inline size_t capacity()const { return _nBuffer; }

	//缺省缓冲数量
	inline size_t defaultBuffer() const { return _nDefaultBuffer; }

	//设置缺省缓冲数量
	inline void defaultBuffer(const size_t& nDefaultBuffer) { _nDefaultBuffer = nDefaultBuffer; }

	//是否为空
	inline bool isEmpty() { return _nLength == 0; }
	 

	//----------------------------------------------------------------------------------------------------操作
	//查找元系的最大值
	inline const T* min_() const { return math_::min_<T>(_pData, _nLength); }

	//查找元系的最小值
	inline const T* max_() const { return math_::max_<T>(_pData, _nLength); }

	//开始位置
	inline  T* begin()const { return _pData; }


	// 结束位置
	inline  T* end()const { return _pData + _nLength; }

	//添加单个元素
	T& add(const T& rData);

	//---------------------------------------------------------------------------------------------------------虚拟函数
private:
	//初始化内存
	virtual void initData(const size_t nDefaultBuffer);

public:
	//添加一串元素,pData为数据指针,nLength数据长度
	virtual const T* add(const T* pData, const size_t nLength);

	//删除元系,nStartPos为开始位置,nLength长度
	virtual const T* del(const size_t& nStartPos, const size_t& nLength);

	//清空所有内存,并把指针设为null;
	virtual void clearData();

	//设置缓冲区
	virtual void setBuffer(const size_t& nBuffer);

	//设置缓冲区,兼容std::string
	inline void reserve(const size_t& nBuffer) { setBuffer(nBuffer); }

	//从nStart开始向后查找aTypeValue第一次出现在当前容器中的位置,失败时返回linearmemory_::npos
	inline size_t find_(const T& aTypeValue, const size_t nStart = 0) const { return math_::find(_pData, _nLength, &aTypeValue, 1, nStart); }

	//从nStart开始向后查找长度为pFindLength的pFind数据第一次出现在当前容器中的位置,失败时返回linearmemory_::npos
	inline size_t find_(const T* pFind, const size_t& nStart, const size_t& pFindLength) const { return math_::find(_pData, _nLength, pFind, pFindLength, nStart); }

	//从nStart开始向后查找aFindLLinearList第一次出现在当前容器中的位置,失败时返回linearmemory_::npos 
	size_t find_(const linearmemory_& aFindLLinearList, const size_t& nStart = 0) const { return math_::find(_pData, _nLength, aFindLLinearList._pData, aFindLLinearList._nLength, nStart); }



	//从nStart开始向前查找aTypeValue第一次出现在当前容器中的位置,失败时返回linearmemory_::npos。
	inline size_t rfind_(const T& aTypeValue, const size_t& nStart = npos) const { return math_::rfind(_pData, _nLength, &aTypeValue, 1, nStart); }

	//从nStart开始向前查找长度为pFindLength的pFind数据第一次出现在当前容器中的位置,失败时返回linearmemory_::npos
	inline size_t rfind_(const T* pFind, const size_t& nStart, const size_t& pFindLength) const { return math_::rfind(_pData, _nLength, pFind, pFindLength, nStart); }

	//从nStart开始向前查找aFindLLinearList第一次出现在当前容器中位置,失败时返回linearmemory_::npos 
	inline size_t rfind_(const linearmemory_& aFindLLinearList, const size_t& nStart = npos) const { return math_::rfind(_pData, _nLength, aFindLLinearList._pData, aFindLLinearList._nLength, nStart); }




	//从nStart开始向后查找aTypeValue第一次出现的位置,失败时返回linearmemory_::npos
	inline size_t find_first_of_(const T& aTypeValue, const size_t& nStart = 0) const { return math_::find_first_of(_pData, _nLength, &aTypeValue, 1, nStart); }

	//从nStart开始向后查找长度为pFindLength的pFind数据任一元素第一次出现的位置,失败时返回linearmemory_::npos
	inline size_t find_first_of_(const T* pFind, const size_t& nStart, const size_t& pFindLength) const { return math_::find_first_of(_pData, _nLength, pFind, pFindLength, nStart); }

	//从nStart开始向后查找aFindLLinearList任一元素第一次出现的位置,失败时返回linearmemory_::npos 
	size_t find_first_of_(const linearmemory_& aFindLLinearList, const size_t& nStart = 0) const { return math_::find_first_of(_pData, _nLength, aFindLLinearList._pData, aFindLLinearList._nLength, nStart); }


	//从nStart开始向后查找aTypeValue第一次不出现的位置,失败时返回linearmemory_::npos
	inline size_t find_first_not_of_(const T& aTypeValue, const size_t& nStart = 0) const { return math_::find_first_not_of(_pData, _nLength, &aTypeValue, 1, nStart); }

	//从nStart开始向后查找长度为pFindLength的pFind数据任一元素第一次不出现的位置,失败时返回linearmemory_::npos
	inline size_t find_first_not_of_(const T* pFind, const size_t& nStart, const size_t& pFindLength) const { return math_::find_first_not_of(_pData, _nLength, pFind, pFindLength, nStart); }

	//从nStart开始向后查找aFindLLinearList任一元素第一次不出现的位置,失败时返回linearmemory_::npos 
	size_t find_first_not_of_(const linearmemory_& aFindLLinearList, const size_t& nStart = 0) const { return math_::find_first_not_of(_pData, _nLength, aFindLLinearList._pData, aFindLLinearList._nLength, nStart); }


	//从nStart开始向前查找aTypeValue第一次出现的位置,成功返回索引处,失败时返回linearmemory_::npos
	inline size_t find_last_of_(const T& aTypeValue, const size_t& nStart = 0) const { return math_::find_last_of(_pData, _nLength, &aTypeValue, 1, nStart); }

	//从nStart开始向前查找pFind中元系第一次出现的位置,成功返回索引处,失败时返回linearmemory_::npos
	inline size_t find_last_of_(const T* pFind, const size_t& nStart, const size_t& pFindLength) const { return math_::find_last_of(_pData, _nLength, pFind, pFindLength, nStart); }


	//从nStart开始向前(倒序)查找aFindLLinearList任一元素第一次出现的位置,找到返回索引处,失败时返回linearmemory_::npos
	size_t find_last_of_(const linearmemory_& aFindLLinearList, const size_t& nStart = 0) const { return math_::find_last_of(_pData, _nLength, aFindLLinearList._pData, aFindLLinearList._nLength, nStart); }



	//从nStart开始向前查找aTypeValue第一次不出现的位置,失败时返回linearmemory_::npos
	inline size_t find_last_not_of_(const T& aTypeValue, const size_t& nStart = 0) const { return math_::find_last_not_of(_pData, _nLength, &aTypeValue, 1, nStart); }

	//从nStart开始向前查找长度为pFindLength的pFind数据任一元素第一次不出现的位置,失败时返回linearmemory_::npos
	inline size_t find_last_not_of_(const T* pFind, const size_t& nStart, const size_t& pFindLength) const { return math_::find_last_not_of(_pData, _nLength, pFind, pFindLength, nStart); }

	//从nStart开始向前查找aFindLLinearList任一元素第一次不出现的位置,失败时返回linearmemory_::npos 
	size_t find_last_not_of_(const linearmemory_& aFindLLinearList, const size_t& nStart = 0) const { return math_::find_last_not_of(_pData, _nLength, aFindLLinearList._pData, aFindLLinearList._nLength, nStart); }




};

template<typename T>
bool linearmemory_<T>::operator==(const linearmemory_<T>& rhs) const
{
	if (_pData == rhs._pData) return true;  //排除 相同引用  class aValue;    if( aValue == aValue)

	if (_pData == nullptr || rhs._pData == nullptr) return false;

	if (_nLength != rhs._nLength) return false;

	for (size_t n = 0; n < rhs._nLength; ++n)
	{
		if (_pData[n] != rhs._pData[n]) return false;
	}
	return true;
}

template<typename T>
bool  linearmemory_<T>::operator!=(const linearmemory_<T>& rhs) const
{
	return (*this == rhs ? false : true);
}


/*
template<typename T>
bool operator==(const linearmemory_<T>& lhs, const linearmemory_<T>& rhs)
{
	if (lhs._pData == rhs._pData) return true;  //排除 相同引用  class aValue;    if( aValue == aValue)

	if (lhs._pData == nullptr || rhs._pData == nullptr) return false;

	if (lhs._nLength != rhs._nLength) return false;

	for (size_t n = 0; n < rhs._nLength; ++n)
	{
		if (lhs._pData[n] != rhs._pData[n]) return false;
	}
	return true;
}


template<typename T>
bool operator!=(const linearmemory_<T>& lhs, const linearmemory_<T>& rhs)
{
	return (lhs == rhs ? false : true);
}

 */


 //添加一串元素,pData为数据指针,nLength数据长度
template<typename T>
const  T* linearmemory_<T>::add(const T* pData, const size_t nLength)
{ 

#ifdef _LF_DEBUG_
	assert(pData != null && nLength != 0);
#endif
	if (_nBuffer >= nLength)
	{
		memory_::memcpy_<T>(_pData + _nLength, pData, nLength);
		_nBuffer -= nLength;
		_nLength += nLength;

	}
	else
	{
		T* pNew = memory_::memNew<T>(_nDefaultBuffer + _nLength + nLength, false);

		if (_nLength > 0)
			memory_::memcpy_<T>(pNew, _pData, _nLength);  //拷贝原来的数据


		memory_::memcpy_<T>(pNew + _nLength, pData, nLength); //拷贝新数据

		if (_nLength + _nBuffer > 0 && _pData != null)
			memory_::memDelete<T>(_pData, _nLength + _nBuffer);  //释放内存		 

		_nLength += nLength;
		_nBuffer = _nDefaultBuffer;
		_pData = pNew;

	}

	return this->_pData;
}



//删除元系,nStartPos为开始位置,nLength长度
template<typename T>
const  T* linearmemory_<T>::del(const size_t& nStartPos, const size_t& nLength)
{
	if (nStartPos + nLength > _nLength)
	{
		_nBuffer = _nBuffer + _nLength - nStartPos;
		_nLength = nStartPos + 1;
	}
	else if (nStartPos + nLength >= _nLength)
	{
		_nLength -= nLength;
		_nBuffer += nLength;
	}
	else
	{
		for (size_t n = nStartPos + nLength; n < _nLength; ++n)
		{
			_pData[n - nLength] = _pData[n];
		}
		_nLength -= nLength;
		_nBuffer += nLength;
	}

	return _pData;
}



template<typename T>
void  linearmemory_<T>::initData(const size_t nDefaultBuffer)
{
	_nDefaultBuffer = nDefaultBuffer;
	_nBuffer = nDefaultBuffer;
	_nLength = 0;
	_pData = null;


	if (_nBuffer > 0)
		_pData = memory_::memNew<T>(nDefaultBuffer, false);

	//std::cout << typeid(this).name()  << "nDefaultBuffer=" << nDefaultBuffer << "\n"; 
}



//返回最后加入的元素的引用
template<typename T>
T& linearmemory_<T>::add(const T& rData)
{
	add(&rData, 1);
	return *(_pData + _nLength - 1);
}



template<typename T>
linearmemory_<T>::linearmemory_(const size_t nDefaultBuffer)
{
	/*
	构造函数中不能调用虚函数
	指的是直接或者隐式使用 this指针调用虚函数
	由于,不能确定
	this指针所代表的对象,包括其中指向虚函数表的指针,有没有构造完成,即包括指向虚函数表的指针在内的所有成员有没有,完全构造完成,所以难以正常使用虚函数。

	更重要的就是一些指针,还没有构造的时候,就用到了--这是野指针--,结果不确定!!!
	比如有一个 char指针,起到类似 string 的作用,只是需要动态分配内存,没有分配内存时,就是个野指针,一旦 使用的虚函数,使用了这个指针,后果就很严重。
	更严重的问题是,基类对子类的虚函数,如何使用完全没有谱,因为子类还没有定义。

	而且没有任何标志,表示虚函数表指针构造完成。
	虚函数没法调用。

	有标志也不行,子类会更改,虚函数表指针;
	虚函数表指针,会随着父类->子类;逐层构造,逐渐更改。
	PS:
	关于
	2.构造函数中调用结果运行行为正常,即已具有正常多态行为(因为在进入构造函数函数体之前,构造对象的虚函数表,对象中虚函数表指针,对象成员都已初始化完成,已是完整的派生类对象)。

	这个说法有问题,父类正在构造时候,子类对象,并没有开始构造,父类对象构造完成后,才会开始子类的构造,这时才会把虚函数表的指针,改成子类的虚函数表指针,这是单继承。
	多继承更复杂。
	*/

	initData(nDefaultBuffer);  //子类的initData虚函数还未构造

	//std::cout << "构造函数:linearmemory_<T>::linearmemory_(size_t nDefaultBuffer)" << "\n";
	 
}

template<typename T>
linearmemory_<T>::linearmemory_(const T* pType, const size_t nCount, const size_t nDefaultBuffer)
{
	initData(0);
	_nDefaultBuffer = nDefaultBuffer;

	add(pType, nCount);
}


template<typename T>
linearmemory_<T>::linearmemory_(const linearmemory_& rhs)
{
	_nDefaultBuffer = rhs._nDefaultBuffer;
	_nBuffer = rhs._nBuffer;
	_nLength = rhs._nLength;
	_pData = memory_::memNew<T>(_nLength + _nBuffer, false);

	memory_::memcpy_(_pData, rhs._pData, _nLength + _nBuffer);
}


#if _MSC_VER

template<typename T>
linearmemory_<T>::linearmemory_(std::initializer_list<T> aList)
{
	initData(aList.size() + 5);
	add(aList.begin(), aList.size());
}

#endif


template<typename T>
linearmemory_<T>::~linearmemory_()
{
	clearData();
}

//清空所有内存,并把指针设为null;
template<typename T>
void linearmemory_<T>::clearData()
{
	if (_nLength + _nBuffer > 0 && _pData != null)
	{
		memory_::memDelete<T>(_pData, _nLength + _nBuffer);
		_nLength = 0;
		_nBuffer = 0;
	}
	else
	{
		_nBuffer = 0;
		_nLength = 0;
	}
}

//设置缓冲区大小
template<typename T>
void linearmemory_<T>::setBuffer(const size_t& nBuffer)
{
	//std::cout << "virtual void linearmemory_<T>::setBuffer(const size_t& nBuffer)" << "\n";

	if (_nBuffer == nBuffer)
		return;

	if (nBuffer == 0) return;


	T* pNew = memory_::memNew<T>(_nLength + nBuffer, false);

	if (_nLength > 0)
		memory_::memcpy_(pNew, _pData, _nLength);

	memory_::memDelete<T>(_pData, _nLength + _nBuffer);

	_pData = pNew;
	_nBuffer = nBuffer;
}


template<typename T>
linearmemory_<T>& linearmemory_<T>::operator=(const linearmemory_<T>& rhs)
{
	if (&rhs != this)
	{
		if (&rhs != null && rhs._nLength != 0)
		{
			memory_::memDelete<T>(_pData, _nLength + _nBuffer);

			_nDefaultBuffer = rhs._nDefaultBuffer;
			_nBuffer = rhs._nBuffer;
			_nLength = rhs._nLength;
			_pData = memory_::memNew<T>(_nLength + _nBuffer, false);

			memory_::memcpy_(_pData, rhs._pData, _nLength + _nBuffer);
		}
		else
		{
			clearData();
		}
	}

	return *this;
}


//重载的下标操作符
template<typename T>
T& linearmemory_<T>::operator[](const size_t& nIndex) const
{
	assert(nIndex < _nLength);

	return _pData[nIndex];
}


template<typename T>
std::ostream& operator<<(std::ostream& os, const linearmemory_<T>& aLinearList)
{
	/*
	for (size_t n = 0; n < aLinearList.count(); ++n)
	{
		os << aLinearList[n] << "\t";
		if ( (n+1) % 5 == 0)	os << "\n";
	}
	os << "\n";
	*/
	for (size_t n = 0; n < aLinearList.length(); ++n)
	{
		os << aLinearList[n] << "\n";
	}
	return os;
}




_LF_END_
#endif // !_LLINEARLISH_H_

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Visual Studio 2022 C++ CLR 的艰难除 Bug 的相关文章

  • 网页bug怎么都测不出来?赶紧进来看看吧

    2024软件测试面试刷题 这个小程序 永久刷题 靠它快速找到工作了 刷题APP的天花板 CSDN博客 文章浏览阅读2 2k次 点赞85次 收藏11次 你知不知道有这么一个软件测试面试的刷题小程序 里面包含了面试常问的软件测试基础题 web自
  • 为什么 .NET JIT 编译器决定不内联或优化对没有副作用的空静态方法的调用?

    我认为我观察到 NET JIT 编译器没有内联或优化对没有副作用的空静态方法的调用 考虑到一些定制的在线资源 这有点令人惊讶 我的环境是 x64 Windows 8 1 NET Framework 4 5 上的 Visual Studio
  • GCHandle.FromIntPointer 未按预期工作

    这是一个非常简单 完整 的程序 用于练习 GCHandle FromIntPointer 的使用 using System using System Runtime InteropServices namespace GCHandleBug
  • Browser.ReadyState 上的致命执行错误[重复]

    这个问题在这里已经有答案了 可能的重复 NET 致命执行引擎错误 故障排除 https stackoverflow com questions 2823440 troubleshooting net fatal execution engi
  • Oracle Data Provider 到 CLR 类型的映射

    在哪里可以找到 ODP 到 CLR 类型映射的列表 在 Oracle 数据库上 NUMBER 9 0 类型在 NET 应用程序中作为 MS Oracle 驱动程序中的 System Decimal 出现 但在 ODP 驱动程序中作为 Sys
  • C# 对象引用如何在内存中/运行时(在 CLR 中)表示?

    我很想知道 C 对象引用在运行时 在 NET CLR 中 如何在内存中表示 我想到的一些问题是 对象引用占用多少内存 在类的范围和方法的范围中定义时有什么不同吗 它所在的位置是否根据此范围 堆栈与堆 而有所不同 对象引用中维护的实际数据是什
  • 为什么结构对齐取决于字段类型是原始类型还是用户定义的?

    In 野田时间 http nodatime orgv2 我们正在转向纳秒分辨率 这意味着我们不能再使用 8 字节整数来表示我们感兴趣的整个时间范围 这促使我研究 Noda Time 的 许多 结构体的内存使用情况 这反过来又引导我发现 CL
  • 使用 .NET 4.0、3.5 时,UnmanagedFunctionPointer 会导致堆栈溢出

    我在点击处理程序中有一个简单的函数 它有一个 try catch 块 如果我在此 try catch 块中抛出异常 它会成功捕获异常 如果我在抛出异常之前调用非托管 DLL 则异常不会被处理且不会被捕获 未修改的 DLL 调用正在做什么 可
  • CLR 可以支持“函数指针”值类型吗?

    前几天我问过为什么委托是引用类型 https stackoverflow com questions 7905962 why are delegates reference types 基于我的错误观念 即委托所需的只是两个引用 一个指向对
  • CorFlags.exe /32BIT+ 如何工作?

    我想我的问题是关于CLR http en wikipedia org wiki Common Language Runtime装载机 我想了解背后的机制CorFlags exe http msdn microsoft com en us l
  • 无法获取价值,因为它已被优化掉

    我在调试时遇到问题 突然间 我在调试时看不到大多数变量的值 我设法在立即窗口中收到两条不同的消息 无法获取本地或参数 参数 的值 因为它在此指令指针处不可用 可能是因为它已被优化掉 and 表达式求值器中出现内部错误 我已经尝试并检查了以下
  • String 和 Char 类型在 .NET 中如何存储在内存中?

    我需要存储一个语言代码字符串 例如 en 它始终包含 2 个字符 将类型定义为 String 还是 Char 更好 private string languageCode vs private char languageCode 或者还有其
  • 用于删除 unbox_any 的抖动逻辑

    我正在调查此 C 代码的执行 public static void Test
  • 启动时依赖 CLR 的程序集解析

    当程序启动时 CLR 是否尝试解析 不一定加载 所有依赖程序集 也就是说 依赖的大会决议是按需完成的吗 请注意 我不是在谈论 Assembly Load Reflective 类型的负载 JIT 编译器负责指导程序集的加载 以响应将 IL
  • 当有大量可用内存时出现 OutOfMemoryException

    我们有一个在 5 个 服务器 节点 16 个核心 每个 128 GB 内存 上运行的应用程序 在每台计算机上加载近 70 GB 的数据 该应用程序是分布式的并为并发客户端提供服务 因此 有大量的套接字使用 类似地 对于多个线程之间的同步 有
  • Marshal.GetFunctionPointerForDelegate 如何作用于实例成员?

    我想知道 Marshal GetFunctionPointerForDelegate 即我想知道它如何将委托转换为非静态函数到函数指针 它是否动态生成以某种方式附加实例的代码存根 如果是这样 这不会泄漏内存吗 也许委托在其终结器中释放了它
  • mscorlib.dll 是 CLR 吗?

    如果这不是我几乎可以肯定的 那么 mscorlib dll 的作用是什么以及 CLR 位于哪里 CLR不在mscorlib dll but in MSCorEE dll 我想这就是你正在寻找的 这是加载 NET exe 程序集时加载的主 D
  • 为什么值类型存储在堆栈中?

    为什么 C Net 更喜欢使用堆栈来存储值类型 这种设计背后的主要原因是什么 是因为对堆栈的读 写操作更好地利用了机器处理器吗 另外 也许你可以证明为什么其他人不可以 埃里克 利珀特讨论了这个here https learn microso
  • C++/CLR 托管单元测试存在链接器错误

    当将任何托管类包含到我的托管单元测试中时 编译会输出以下错误 1 gt UnitTest obj error LNK2020 unresolved token 0A000360 extern C int cdecl CrtDbgReport
  • C# 中如何实现引用返回?

    既然 C GC 可以移动内存 那么如何实现引用返回呢 下面的代码会导致 未定义的行为 吗 public struct Record public int Hash public VeryLargeStruct Data public cla

随机推荐