Mfc里,carray 用法的GetAt问题。

  需要包含的头文件 &afxtempl.h&
  CArray类支持与C arrays相似的,但是必要时可以动态压缩并扩展。数组索引从0开始。可以决定是固定数组还是允许当添加元素时扩展当前的边界。内存对上界是连续地分配空间,甚至一些元素可为空。
  和C arrays一样,CArray索引元素的访问时间是不变的,与数组大小无关。
  提示:
  在使用一个数组之前,使用SetSize建立它的大小和为它分配内存。如果不使用SetSize,则为数组添加元素就会引起频繁地重新分配和拷贝。频繁地重新分配和拷贝不但没有效率,而且导致内存碎片。
  如果需要一堆数组中的个别数据,必须设置CDumpContext对象的深度为1或更大。
  此类的某成员函数调用全局帮助函数,它必须为CArray的大多数使用而定制。请参阅宏和全局量部分中的&类收集帮助器&。
  当从一个CArray对象中移去元素时,帮助函数DestructElements被调用。
  当添加元素时,帮助函数ConstructElements被调用。
  数组类的派生与列表的派生相似。
  MFC提供了一套模板库,来实现一些比较常见的如Array,List,Map。CArray即为其中的一个,用来实现的功能。CArray是从CObject派生,有两个模板参数,第一个参数就是CArray类数组元素的变量类型,后一个是函数调用时的参数类型。有一个类 class Object,要定义一个Object的动态数组,那么可以用以下两种方法:
  CArray&Object,Object& Var1;
  CArray&Object,Object&& Var2;
  Var2的效率要高。
  先了解一下CArray中的成员变量及作用。TYPE* m_pD // 数据保存地址的指针
  int m_nS // 用户当前定义的数组的大小
  int m_nMaxS // 当前实际分配的数组的大小
  int m_nGrowBy; // 分配内存时增长的元素个数
  构造函数,对成员变量进行了初始化。
  CArray&TYPE, ARG_TYPE&::CArray()
  m_pData = NULL;
  m_nSize = m_nMaxSize = m_nGrowBy = 0;
  SetSize成员函数是用来为数组分配空间的。SetSize的函数定义如下:
  void SetSize( int nNewSize, int nGrowBy = -1 );
  nNewSize 指定数组的大小
  nGrowBy 如果需要增加数组大小时增加的元素的个数。
  对SetSize的代码,进行分析。
  void CArray&TYPE, ARG_TYPE&::SetSize(int nNewSize, int nGrowBy)
  if (nNewSize == 0)
  // 第一种情况
  // 当nNewSize为0时,需要将数组置为空,
  // 如果数组本身即为空,则不需做任何处理
  // 如果数组本身已含有数据,则需要清除数组元素
  if (m_pData != NULL)
  //DestructElements 函数实现了对数组元素析构函数的调用
  //不能使用delete m_pData 因为我们必须要调用数组元素的析构函数
  DestructElements&TYPE&(m_pData, m_nSize);
  //现在才能释放内存
  delete[] (BYTE*)m_pD
  m_pData = NULL;
  m_nSize = m_nMaxSize = 0;
  else if (m_pData == NULL)
  // 第二种情况
  // 当m_pData==NULL时还没有为数组分配内存
  //首先我们要为数组分配内存,sizeof(TYPE)可以得到数组元素所需的字节数
  //使用new 数组分配了内存。注意,没有调用构造函数
  m_pData = (TYPE*) new BYTE[nNewSize * sizeof(TYPE)];
  //下面的函数调用数组元素的构造函数
  ConstructElements&TYPE&(m_pData, nNewSize);
  //记录下当前数组元素的个数
  m_nSize = m_nMaxSize = nNewS
  else if (nNewSize &= m_nMaxSize)
  // 第三种情况
  // 这种情况需要分配的元素个数比已经实际已经分配的元素个数要少
  if (nNewSize & m_nSize)
  // 需要增加元素的情况
  // 与第二种情况的处理过程,既然元素空间已经分配,
  // 只要调用新增元素的构造函数就Ok
  ConstructElements&TYPE&(&m_pData[m_nSize], nNewSize-m_nSize);
  else if (m_nSize & nNewSize)
  // 现在是元素减少的情况,我们是否要重新分配内存呢?
  // No,这种做法不好,后面来讨论。
  // 下面代码释放多余的元素,不是释放内存,只是调用析构函数
  DestructElements&TYPE&(&m_pData[nNewSize], m_nSize-nNewSize);
  m_nSize = nNewS
  //这是最糟糕的情况,因为需要的元素大于m_nMaxSize,
  // 意味着需要重新分配内存才能解决问题
  // 计算需要分配的数组元素的个数
  int nNewM
  if (nNewSize & m_nMaxSize + nGrowBy)
  nNewMax = m_nMaxSize + nGrowBy;
  nNewMax = nNewS
  // 重新分配一块内存
  TYPE* pNewData = (TYPE*) new BYTE[nNewMax * sizeof(TYPE)];
  //实现将已有的数据复制到新的的内存空间
  memcpy(pNewData, m_pData, m_nSize * sizeof(TYPE));
  // 对新增的元素调用构造函数
  ConstructElements&TYPE&(&pNewData[m_nSize], nNewSize-m_nSize);
  //释放内存
  delete[] (BYTE*)m_pD
  //将数据保存
  m_pData = pNewD
  m_nSize = nNewS
  m_nMaxSize = nNewM
  下面是ConstructElements函数的实现代码template&class TYPE&
  AFX_INLINE void AFXAPI ConstructElements(TYPE* pElements, int nCount)
  // first do bit-wise zero initialization
  memset((void*)pElements, 0, nCount * sizeof(TYPE));
  for (; nCount--; pElements++)
  ::new((void*)pElements) TYPE;
  ConstructElements是一个模板函数。对构造函数的调用是通过标为黑体的代码实现的。可能很多人不熟悉new 的这种用法,它可以实现指定的内存空间中构造类的实例,不会再分配新的内存空间。类的实例产生在已经分配的内存中,并且new操作会调用对象的构造函数。因为vc中没有办法直接调用构造函数,而通过这种方法,巧妙的实现对构造函数的调用。
  再来看DestructElements 函数的代码template&class TYPE&
  AFX_INLINE void AFXAPI DestructElements(TYPE* pElements, int nCount)
  for (; nCount--; pElements++)
  pElements-&~TYPE();
  DestructElements函数同样是一个模板函数,实现很简单,直接调用类的析构函数即可。
  如果定义一个CArray对象 CArray&Object,Object&& myObject ,对myObject就可象数组一样,通过下标来访问指定的数组元素。
  CArray[]有两种实现,区别在于返回值不同。
  template&class TYPE, class ARG_TYPE&
  AFX_INLINE TYPE CArray&TYPE, ARG_TYPE&::operator[](int nIndex) const
  { return GetAt(nIndex); }
  template&class TYPE, class ARG_TYPE&
  AFX_INLINE TYPE& CArray&TYPE, ARG_TYPE&::operator[](int nIndex)
  { return ElementAt(nIndex); }
  前一种情况是返回的对象的实例,后一种情况是返回对象的引用。分别调用不同的成员函数来实现。
  TYPE GetAt(int nIndex) const
  { ASSERT(nIndex &= 0 && nIndex & m_nSize);
  return m_pData[nIndex]; }
  TYPE& ElementAt(int nIndex)
  { ASSERT(nIndex &= 0 && nIndex & m_nSize);
  return m_pData[nIndex]; }
  除了返回值不同,其它都一样.
  CArray&int,int&& arrI
  arrInt.SetSize(10);
  int n = arrInt.GetAt(0);
  int& l = arrInt.ElementAt(0);
  cout && arrInt[0] &&
  n = 10;
  cout && arrInt[0] &&
  l = 20;
  count && arrInt[0] &&
  结果会发现,n的变化不会影响到数组,而l的变化会改变数组元素的值。实际即是对C++中引用运算符的运用。
  CArray下标访问是非安全的,它并没有超标预警功能。虽然使用ASSERT提示,但下标超范围时没有进行处理,会引起非法内存访问的错误。
  Add函数的作用是向数组添加一个元素。下面是它的定义: int CArray&TYPE, ARG_TYPE&::Add(ARG_TYPE newElement).Add函数使用的参数是模板参数的二个参数,也就是说,这个参数的类型是我们来决定的,可以使用Object或Object&的方式。熟悉C++的朋友都知道,传引用的效率要高一些。如果是传值的话,会在堆栈中再产生一个新的对象,需要花费更多的时间。
  template&class TYPE, class ARG_TYPE&
  AFX_INLINE int CArray&TYPE, ARG_TYPE&::Add(ARG_TYPE newElement)
  int nIndex = m_nS
  SetAtGrow(nIndex, newElement);
  return nI
  它实际是通过SetAtGrow函数来完成这个功能的,它的作用是设置指定元素的值。
  template&class TYPE, class ARG_TYPE&
  void CArray&TYPE, ARG_TYPE&::SetAtGrow(int nIndex, ARG_TYPE newElement)
  if (nIndex &= m_nSize)
  SetSize(nIndex+1, -1);
  m_pData[nIndex] = newE
  SetAtGrow的实现也很简单,如果指定的元素已经存在,就把改变指定元素的值。如果指定的元素不存在,也就是 nIndex&=m_nSize的情况,就调用SetSize来调整数组的大小
  首先定义
  CArray&char *& arryPC
  这里以定义char*的为例子。
  接下来我们来熟悉CArray这个类里的函数。
  INT_PTR GetCount()
  获得当前这个数组有多少个元素。
  void SetSize(INT_PTR nNewSize, INT_PTR nGrowBy = -1);
  设置数组的大小。
  TYPE& GetAt(INT_PTR nIndex);
  void SetAt(INT_PTR nIndex, ARG_TYPE newElement);
  获得/设置序列的元素
  INT_PTR Add(ARG_TYPE newElement);
  在数组的末尾添加一个元素,数组的长度加1。如果之前使用SetSize是nGrowBy大于1,则内存按照nGrowBy增加。函数返回newElement的数组元素索引
  void RemoveAt(INT_PTR nIndex, INT_PTR nCount = 1);
  从指定的nIndex位置开始,删除nCount个数组元素,所有元素自动下移,并且减少数组的上限,但是不释放内存。这里我们自己手动的申请的就必须自己释放。new对应delete相信大家都知道的。
  void RemoveAll();
  从数组中移除素有的元素,如果数组为空,该行数也起作用。
  INT_PTR Append(const CArray& src);
  将同个类型的一个数组A附加到本数组的尾部,返回A第一数组元素在本数组的索引。
  void InsertAt(INT_PTR nIndex, ARG_TYPE newElement, INT_PTR nCount = 1);
  void InsertAt(INT_PTR nStartIndex, CArray* pNewArray);
  在指定的nIndex或者nStartIndex位置插入nCount个newElement数组元素或者pNewArray数组
  下面是我应用的实例:
  view plaincopy to clipboardprint?
  CArray &char*&arrPC
  //初始化元素
  arrPChar.SetSize(10);
  for (int i=0;i&10;i++)
  char *aChar=new char[10];
  strcpy_s(aChar,10,"hello arr");
  arrPChar.SetAt(i,aChar);
  //在数组的末尾插入一个元素
  char *bChar = new char[10];
  strcpy_s(bChar,10,"asdfefdsd");
  arrPChar.Add(bChar);
  //在索引2的位置插入一个元素,即在第三位插入一个元素
  char *cChar=new char[5];
  strcpy_s(cChar,5,"aidy");
  arrPChar.InsertAt(2,cChar);
  for (int j=0;j&arrPChar.GetCount();j++)
  TRACE("%d,%s\n",j,arrPChar.GetAt(j));
  //删除数组里的所有元素,要释放内存,如果单单Remove的话则内存不会被释放
  //这里因为使用RemoveAll的话内存无法被释放,所以没有给实例。
  int count = arrPChar.GetCount();
  for (int k=0; k& k++)
  char *dChar=arrPChar.GetAt(0);
  arrPChar.RemoveAt(0);
  delete dC
阅读(...) 评论()CArray使用_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
喜欢此文档的还喜欢
CArray使用
下​我​的​另​一​份​完​整​版​的​吧​…​…
阅读已结束,如果下载本文需要使用
想免费下载本文?
把文档贴到Blog、BBS或个人站等:
普通尺寸(450*500pix)
较大尺寸(630*500pix)
你可能喜欢CArray Members (MFC)
CArray Members
Visual Studio 2005
Base Class Members
Constructs an empty array.
Gets the number of elements in this array.
Gets the number of elements in this array.
Returns the largest valid index.
Determines whether the array is empty.
Sets the number of elements to be contained in this array.
Frees all unused memory above the current upper bound.
Removes all the elements from this array.
Relocates data to a new buffer when the array should grow or shrink.
Returns a temporary reference to the element pointer within the array.
Returns the value at a given index.
Allows access to elements in the array. Can be NULL.
Sets the val array not allowed to grow.
Adds an element to
grows the array if necessary.
Appends anothe grows the array if necessary
Copies anothe grows the array if necessary.
Sets the val grows the array if necessary.
Inserts an element (or all the elements in another array) at a specified index.
Removes an element at a specific index.
Sets or gets the element at the specified index.
您对此内容的反馈非常重要。请告诉我们您的想法。
更多反馈?
1500 个剩余字符
我们非常感谢您的反馈。
开发人员中心CArray::GetAt
CArray::GetAt
Visual Studio 2013
Returns the array element at the specified index.
TYPE& GetAt(
INT_PTR nIndex
const TYPE& GetAt(
INT_PTR nIndex
Template parameter specifying the type of the array elements.
An integer index that is greater than or equal to 0 and less than or equal to the value returned by .
The array element currently at this index.
Passing a negative value or a value greater than the value returned by GetUpperBound will result in a failed assertion.
CArray&CPoint,CPoint& myA
// Add elements to the array.
for (int i = 0; i & 10; i++)
myArray.Add(CPoint(i, 2 * i));
// Modify all the points in the array.
for (int i = 0; i &= myArray.GetUpperBound(); i++)
pt = myArray.GetAt(i);
myArray.SetAt(i, pt);
Header: afxtempl.h
Your feedback about this content is important.Let us know what you think.
Additional feedback?
1500 characters remaining
Thank you!
We appreciate your feedback.
Have a suggestion to improve MSDN Library?
Visit our UserVoice Page to submit and vote on ideas!
Dev centers
Learning resources}

我要回帖

更多关于 carray 用法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信