运行结果:
还是没发现问题,程序根本没有调用这些构造函数,难道问题在基类。
经过几小时后,最后发现我还定义了一个构造函数,粗心忘记了:
语句:
_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_.h
作者 : 李锋
功能 :内存操作
创建时间 : 2016年7月6日
最后一次修改时间 : 2016年7月23日
********************************************************************************************/
#ifndef _MEMORY__H_
#define _MEMORY__H_
#include"macro_.h"
#include
_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 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_(new T[nCount], nCount, T());
}
else
{
return new T[nCount];
}
}
//释放内存
template static void memDelete(T *pMemory, size_t nCount)
{
_obj_used -= nCount;
_mem_used -= sizeof(T) * nCount;
delete[] pMemory;
pMemory = null;
}
//设置值
template 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)
///
///
///
///
///
///
///
///
/// 创建时间: ????-??-?? 最后一次修改时间:2021-10-26
template 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:
};
///
/// 内存管理,内存自动释放
///
///
template
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(nCount, false);
}
~mem() {
memory_::memDelete(data, _nCount);
}
};
_LF_END_
#endif //--------------------------------------------------------------------------- !_memory__H_
str_.h
/*******************************************************************************************
文件名 : str_.h
功能 : 模拟std::string C# String Java.String
程序字体 : Consolas,11
作者 : 李锋
手机 : 13828778863
Email : [email protected]
创建时间 : 2016年07月06日
------------------------------最后一次修改时间:2022年11月03日
***********************************************************************************************/
#ifndef _STR__H_
#define _STR__H_
#include
#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);
///
/// 如果不定义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" 编译不了。
///
///
///
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
#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_(_pData + _nLength, pData, nLength);
_nBuffer -= nLength;
_nLength += nLength;
}
else
{
char_* pNew = memory_::memNew(_nDefaultBuffer + _nLength + nLength + 1, false);
if (_nLength > 0)
memory_::memcpy_(pNew, _pData, _nLength); //拷贝原来的数据
memory_::memcpy_(pNew + _nLength, pData, nLength); //拷贝新的内存
memory_::memDelete(_pData, _nLength + _nBuffer + 1); //释放内存
_nLength += nLength;
_nBuffer = _nDefaultBuffer;
_pData = pNew;
}
_pData[_nLength] = 0;
return this->_pData;
}
///
/// 初始化数据,并设置缓冲区大小
///
///
/// 创建时间: ????-??-?? 最后一次修改时间: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(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;
}
///
/// 设置缓冲区
///
///
/// 创建时间: 2022-10-07 最后一次修改时间:2022-10-07
void str_::setBuffer(const size_t& nBuffer)
{
//std::cout << "virtual void linearmemory_::setBuffer(const size_t& nBuffer)" << "\n";
if (_nBuffer == nBuffer)
return;
if (nBuffer == 0) return;
char_* pNew = memory_::memNew(_nLength + nBuffer, false); //分配新内存
if (_nLength > 0) { memory_::memcpy_(pNew, _pData, _nLength); } //拷贝旧数据
memory_::memDelete(_pData, _nLength + _nBuffer + 1); //空字符点一位
_pData = pNew;
_nBuffer = nBuffer;
}
///
/// 补位4,用0替代,返回一个副本,例如:
/// 1 => 0001
/// 10 => 0010
/// 99999 => 9999
///
///
///
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);
}
}
//---------------------------------------------------------------------------------构造与析构
///
/// 默认为15个字符的缓冲大小
///
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);
}
}
///
///
///
///
///
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_(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);
}
}
///
/// 拷贝构造函数
///
/// 要拷贝的字符串
/// 要拷贝的字符串长度
/// 从那里开始拷贝,索引从零开始
/// 要拷贝的长度
/// 字符串区缓冲区长度
/// 创建时间: ????-??-?? 最后一次修改时间: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(_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_::~LinearList()
++_nLength;
}
//--------------------------------------------------------------------------------模似CSharp字符串String
//
// 摘要:
// 报告指定字符在此实例中的第一个匹配项的从零开始的索引。 搜索从指定字符位置开始,并检查指定数量的字符位置。
//
// 参数:
// value:
// 要查找的 Unicode 字符。
//
// startIndex:
// 搜索起始位置。
//
// count:
// 要检查的字符位置数。
//
// 返回结果:
// 如果找到该字符,则为从字符串的起始位置开始的 value 从零开始的索引位置;否则为 -1。
//
// 异常:
// T:System.ArgumentOutOfRangeException:
// count 或 startIndex 为负数。 - 或 - startIndex 大于此字符串的长度。 - 或 - count 大于此字符串的长度减 startIndex。
///
///
///
///
///
///
///
/// 创建时间: 2021-10-28 最后一次修改时间:2021-10-28 优化测式: 否
int str_::csharp_indexOf(const char_& value, const int& startIndex, const int& count)const
{
//return math_::find(&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);
}
///
/// 返回除去两边的空格和控制字符
///
///
/// 创建时间: 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);
}
///
/// 除去两边的字符 ch
///
///
///
/// 创建时间: 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);
}
///
/// 返回副本
///
///
/// 创建时间: 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;
}
///
///
///
///
///
/// 创建时间: 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;
}
///
///
///
///
///
///
///
/// 创建时间: 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);
}
///
///
///
///
///
/// 创建时间: 2021-10-04 最后一次修改时间:2021-10-04
str_ str_::java_valueOf(const __int64& iNumber)
{
mem 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_& linearmemory_::operator=(const linearmemory_ &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;
}
///
///
///
///
///
///
/// 创建时间: 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;
}
///
/// 保留小数位,四舍五入
///
/// 保留小数位的数字
/// 保留小数的位数
///
/// 创建时间: ????-??-?? 最后一次修改时间: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
作者 : 李锋
功能 : 线性表
创建时间 : 2016年07月16日
最后一次修改时间 : 2016年09月26日
********************************************************************************************/
#ifndef _LINEARMEMORY__H_
#define _LINEARMEMORY__H_
#include
#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
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_ 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提供的新类型,定义在头文件中。
template< class T >
class initializer_list;
先说它的用处吧,然后再详细介绍一下。
首先有了initializer_list之后,对于STL的container的初始化就方便多了,比如以前初始化一个vector需要这样:
int a[] = {0, 1, 2, 3};
std::vector vec(a, a+sizeof(a));
或者
std::vector 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 const nameToBirthday = {
{"lisi", "18841011"},
{"zhangsan", "18850123"},
{"wangwu", "18870908"},
{"zhaoliu", "18810316"},
};
}
复制代码
当然啦,里面的std::map必须提供参数为initializer_list的构造函数如:
*/
#if _MSC_VER
linearmemory_(std::initializer_list 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_的
template
friend bool operator== (const linearmemory_& lhs, const linearmemory_& rhs);
template
friend bool operator!= (const linearmemory_& lhs, const linearmemory_& 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_(_pData, _nLength); }
//查找元系的最小值
inline const T* max_() const { return math_::max_(_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
bool linearmemory_::operator==(const linearmemory_& 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
bool linearmemory_::operator!=(const linearmemory_& rhs) const
{
return (*this == rhs ? false : true);
}
/*
template
bool operator==(const linearmemory_& lhs, const linearmemory_& 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
bool operator!=(const linearmemory_& lhs, const linearmemory_& rhs)
{
return (lhs == rhs ? false : true);
}
*/
//添加一串元素,pData为数据指针,nLength数据长度
template
const T* linearmemory_::add(const T* pData, const size_t nLength)
{
#ifdef _LF_DEBUG_
assert(pData != null && nLength != 0);
#endif
if (_nBuffer >= nLength)
{
memory_::memcpy_(_pData + _nLength, pData, nLength);
_nBuffer -= nLength;
_nLength += nLength;
}
else
{
T* pNew = memory_::memNew(_nDefaultBuffer + _nLength + nLength, false);
if (_nLength > 0)
memory_::memcpy_(pNew, _pData, _nLength); //拷贝原来的数据
memory_::memcpy_(pNew + _nLength, pData, nLength); //拷贝新数据
if (_nLength + _nBuffer > 0 && _pData != null)
memory_::memDelete(_pData, _nLength + _nBuffer); //释放内存
_nLength += nLength;
_nBuffer = _nDefaultBuffer;
_pData = pNew;
}
return this->_pData;
}
//删除元系,nStartPos为开始位置,nLength长度
template
const T* linearmemory_::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
void linearmemory_::initData(const size_t nDefaultBuffer)
{
_nDefaultBuffer = nDefaultBuffer;
_nBuffer = nDefaultBuffer;
_nLength = 0;
_pData = null;
if (_nBuffer > 0)
_pData = memory_::memNew(nDefaultBuffer, false);
//std::cout << typeid(this).name() << "nDefaultBuffer=" << nDefaultBuffer << "\n";
}
//返回最后加入的元素的引用
template
T& linearmemory_::add(const T& rData)
{
add(&rData, 1);
return *(_pData + _nLength - 1);
}
template
linearmemory_::linearmemory_(const size_t nDefaultBuffer)
{
/*
构造函数中不能调用虚函数
指的是直接或者隐式使用 this指针调用虚函数
由于,不能确定
this指针所代表的对象,包括其中指向虚函数表的指针,有没有构造完成,即包括指向虚函数表的指针在内的所有成员有没有,完全构造完成,所以难以正常使用虚函数。
更重要的就是一些指针,还没有构造的时候,就用到了--这是野指针--,结果不确定!!!
比如有一个 char指针,起到类似 string 的作用,只是需要动态分配内存,没有分配内存时,就是个野指针,一旦 使用的虚函数,使用了这个指针,后果就很严重。
更严重的问题是,基类对子类的虚函数,如何使用完全没有谱,因为子类还没有定义。
而且没有任何标志,表示虚函数表指针构造完成。
虚函数没法调用。
有标志也不行,子类会更改,虚函数表指针;
虚函数表指针,会随着父类->子类;逐层构造,逐渐更改。
PS:
关于
2.构造函数中调用结果运行行为正常,即已具有正常多态行为(因为在进入构造函数函数体之前,构造对象的虚函数表,对象中虚函数表指针,对象成员都已初始化完成,已是完整的派生类对象)。
这个说法有问题,父类正在构造时候,子类对象,并没有开始构造,父类对象构造完成后,才会开始子类的构造,这时才会把虚函数表的指针,改成子类的虚函数表指针,这是单继承。
多继承更复杂。
*/
initData(nDefaultBuffer); //子类的initData虚函数还未构造
//std::cout << "构造函数:linearmemory_::linearmemory_(size_t nDefaultBuffer)" << "\n";
}
template
linearmemory_::linearmemory_(const T* pType, const size_t nCount, const size_t nDefaultBuffer)
{
initData(0);
_nDefaultBuffer = nDefaultBuffer;
add(pType, nCount);
}
template
linearmemory_::linearmemory_(const linearmemory_& rhs)
{
_nDefaultBuffer = rhs._nDefaultBuffer;
_nBuffer = rhs._nBuffer;
_nLength = rhs._nLength;
_pData = memory_::memNew(_nLength + _nBuffer, false);
memory_::memcpy_(_pData, rhs._pData, _nLength + _nBuffer);
}
#if _MSC_VER
template
linearmemory_::linearmemory_(std::initializer_list aList)
{
initData(aList.size() + 5);
add(aList.begin(), aList.size());
}
#endif
template
linearmemory_::~linearmemory_()
{
clearData();
}
//清空所有内存,并把指针设为null;
template
void linearmemory_::clearData()
{
if (_nLength + _nBuffer > 0 && _pData != null)
{
memory_::memDelete(_pData, _nLength + _nBuffer);
_nLength = 0;
_nBuffer = 0;
}
else
{
_nBuffer = 0;
_nLength = 0;
}
}
//设置缓冲区大小
template
void linearmemory_::setBuffer(const size_t& nBuffer)
{
//std::cout << "virtual void linearmemory_::setBuffer(const size_t& nBuffer)" << "\n";
if (_nBuffer == nBuffer)
return;
if (nBuffer == 0) return;
T* pNew = memory_::memNew(_nLength + nBuffer, false);
if (_nLength > 0)
memory_::memcpy_(pNew, _pData, _nLength);
memory_::memDelete(_pData, _nLength + _nBuffer);
_pData = pNew;
_nBuffer = nBuffer;
}
template
linearmemory_& linearmemory_::operator=(const linearmemory_& rhs)
{
if (&rhs != this)
{
if (&rhs != null && rhs._nLength != 0)
{
memory_::memDelete(_pData, _nLength + _nBuffer);
_nDefaultBuffer = rhs._nDefaultBuffer;
_nBuffer = rhs._nBuffer;
_nLength = rhs._nLength;
_pData = memory_::memNew(_nLength + _nBuffer, false);
memory_::memcpy_(_pData, rhs._pData, _nLength + _nBuffer);
}
else
{
clearData();
}
}
return *this;
}
//重载的下标操作符
template
T& linearmemory_::operator[](const size_t& nIndex) const
{
assert(nIndex < _nLength);
return _pData[nIndex];
}
template
std::ostream& operator<<(std::ostream& os, const linearmemory_& 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_