Many C ++ programmers use the standard template library (STL), because it is easy to implement arrays, linked lists, ing and other containers. In STL, "Container" refers to the object that saves the "data set. However, before STL is available, there is already MFC. In a series of classes called "MFC collection classes", MFC provides its own array, linked list, And ing implementation methods. Although it is safe to use STL in MFC, many MFC programmers prefer to use the MFC collection class. On the one hand, they are more familiar with MFC, on the other hand, it is unwilling to link two independent class libraries to increase the EXE size of the application. The collection classes in STL are good across platforms and have many generic algorithms.
1. Array
One of the biggest defects of C and C ++ is that arrays do not perform boundary checks. The following Code reflects the most common errors in C and C ++ applications:
This code error occurs because the value of the last iteration in the for loop exceeds the range of the array. An invalid access error occurs during running.
C ++ programmers often solve this problem by writing array classes and checking the boundaries within the classes. The array classes provided below have get and set functions, and use the subscript passed to them by checking. If the passed subscript is invalid, the assertion will be processed:
This will avoid illegal access errors.
1.1mfc array class
You don't have to write array classes yourself. MFC already provides a variety of arrays. First, it is a general carray class, which is actually a template class, it can be used to create "type security array" of any data type ". The carray is defined in the header file afxtempl. h. Second, it is a non-templated array class designed to save specific types of arrays. These classes are defined in afxcoll. h. The following describes non-templated array classes and their stored data types:
Cbytearray 8-bit (byte)
Cwordarray 16-bit (word)
Cdwordarray 32-bit dual-byte (DWORD)
Cuintarray unsigned integer (uint)
Cstringarray cstring
Cobarray cobject pointer
Cptrarray void pointer
As long as you learn to use one of these array classes, other array classes will be used, because they share a common group of functions. The following example declares an array containing 10 uint and initializes it with numbers 1-10:
In both examples, setsize is used to specify that the array contains 10 elements. The [] operator is used to call the setat function of the array, this function copies the value to the element at the specified position in the array. If the array boundary is invalid, the program executes assertion processing. The boundary check is embedded in the satat code: assert (nindex> = 0 & nindex <= m_nsize); this code can be seen in the afxcoll. INL file of the MFC source program.
You can use the insertat function to insert element items to the array without overwriting existing array items. Unlike setat, setat only assigns values to existing array elements. insertat also assigns space to new elements, which are completed by moving the elements after the insertion point backward. Insertat is one of the easy-to-use functions that specify to increase the array size when new element items are added to the array. The [] operator calls the getat function, which retrieves a value from the specified position in the array (of course, the boundary check is required ). You can call getat directly if you want, instead of using the [] operator.
To determine the number of elements contained in an array, you can call the getsize function of the array, or call getupperbound to return the upper-bound subscript of the array, because the subscript starts from 0, therefore, the value is 1 less than the total number of array elements.
The array class of MFC provides two functions for removing elements from an array: removeat and removeall. Removeat deletes one or more elements from the array and moves forward all elements after the deleted elements. Removeall clears the entire array. Both functions adjust the upper bound of the array to reflect the number of deleted element items. If the deleted element is a pointer, it does not delete the object indicated by the pointer. If the array is cptrarray or cobarray type, you must clear the array and delete the objects indicated by the pointer as follows:
If you fail to delete the objects whose addresses are stored in the pointer array, memory leakage occurs.
1.2 dynamically adjust the size of the MFC Array
In addition to border checking, the MFC array class also supports dynamic resizing. The memory allocated to save array elements can be increased or decreased by adding or deleting elements. Therefore, it is not necessary to anticipate the number of elements in an array with dynamic resizing in advance.
One way to dynamically increase the MFC array is to call setsize. You can call setsize to allocate additional memory whenever needed. Suppose 10 element items are set for the array at the beginning, but 20 items are found later. In this case, you only need to allocate space for the additional items by calling setsize for the second time. This method is used to adjust the array size, and the original items still keep their values. Therefore, after setsize is called, the new item needs to be initialized explicitly.
Another way to increase the array is to call setatgrow instead of setat to add element items. For example: cuintarray array; array. setat (0, 1); this code executes assertion processing. Because the array size is 0, setat does not automatically increase the array to accommodate new elements. However, after you change setat to setatgrow, the program runs smoothly. Unlike setat, setatgrow automatically increases the memory allocation space of the array when necessary. The add function also adds elements to the end of the array. Other functions that can automatically increase the array to accommodate new element items include: insertat, append (appending an array to another array), and copy (copying an array to another array)
As new memory needs to be allocated every time the array size increases, increasing arrays frequently in the ethereum will adversely affect the operation and may cause memory fragmentation. The following code:
Cuintarray array;
For (INT I = 0; I <100000; I ++)
Array. Add (I + 1 );
These statements seem very correct, but they are not efficient. They need to apply to allocate thousands of independent memory. This is exactly why MFC asked you to specify "increment" for the second parameter available in setsize. The code below initializes an array more effectively, which tells MFC to allocate 10000 uint memory space each time when more memory is needed.
Cuintarray array;
Array. setsize (0,10000 );
For (INT I = 0; I <100000; I ++)
Array. Add (I + 1 );
Of course, if we allocate space to 100000 elements in advance, the program will be more efficient. However, the number of elements to be saved in the array cannot be foreseen in advance. If we can predict that we can add many elements to the array but cannot determine how much space is needed, it is helpful to specify a large increment. If you do not specify the increment, MFC will select a value for you through the simple formula based on array size. The larger the array, the larger the increase. If the size of the specified array is 0 and setsize is not called at all, the default increment is 4.
The same setsize function can be used to increase the array to reduce array elements. However, when it reduces the number of arrays, setsize does not automatically reduce the buffer for storing array data, unless the freeextra function is called.
1.3 Use carray to create a "type security" array class
Cuintarray, cstringarray, and other MFC array classes are for specific data types. If an array of other data types is required, for example, the cpoint object array, because the cpointarray class does not exist, you must create it from the carray class. Carray is a template class that can be used to create a "type security" array class for any data type.
For clarity, the following uses a self-declared cpoint class to create a "type security" array of the cpoint type and instantiate the class.
Carray <cpoint, cpoint &> array;
The first parameter in the template specifies the Data Type stored in the array, and the second parameter specifies the expression of "type in parameter list.
When using carray and other template-based MFC collection classes, it is important to include the default constructor in the created classes, this is because when a function like insertat is called, MFC uses the default constructor of the class to create a new element.
With carray that can be processed at will, you can use templates instead of the old-fashioned MFC array class such as the item cuintarray. The following statement uses typedef to define a cuintarray data type, which is equivalent to the cuintarray of MFC: typedef carray <uint, uint> cuintarray; the final choice of the class depends on you. However, we recommend that you use the template class as much as possible in the MFC materials, because this can be consistent with modern c ++ programming practices.
2. Linked List
The insert and removeat functions make it easy to add and delete elements to and from arrays. But this simple method of insertion and deletion also has a price: if an element is inserted or deleted in the middle of the array, the high-end elements of the array will move up or down in the memory. When this method is used to process large arrays, this operation is very expensive.
2.1mfc linked list
The template class clist of MFC implements a general linked list, which can be used to customize any data types. MFC also provides the following list of non-template linked lists that process specific data types. These classes are mainly used for compatibility with the old version of MFC and are not frequently used in modern MFC applications.
Class Name Data Type
Coblist cobject pointer
Cptrlist void pointer
Cstringlist cstring
The MFC linked list is a two-way link to facilitate the forward and backward movement operations. The position in the linked list is identified by the abstract value position. For a linked list, position is actually a pointer to the cNode data structure (this structure represents the linked list items in the linked list ). CNode contains three fields: 1. A pointer pointing to the next cNode structure in the Linked List 2. A pointer pointing to the cNode structure in the Linked List 3. Data of the linked list items. The insert operation is fast and efficient, whether at the head of the linked list or at the end of the linked list or at any position specified by position. You can also query the linked list. However, because the query involves sequential records and checks linked list items one by one, it takes a lot of time if the linked list is large.
The addtail function adds a linked list item at the end of the linked list. You can use the addhead function to add a linked list entry to the linked list header. It is also easy to delete a linked list item at the beginning or end of a linked list. You only need to call removehead or removetail. The removeall function deletes all linked list items.
For example, every time you add a string to cstringlist, MFC copies the string to cstring and saves it in the corresponding cNode structure. Therefore, it is acceptable that the string used to initialize the linked list is beyond the range set when the linked list is created.
Once the linked list is successfully created, you can use the getnext and getprev functions to move the Chain List before and after iteration. Both functions accept the "position value indicating the current position in the linked list" and return the linked list item at this position. Both of them must update the position value to reference the next or previous linked list item. You can use getheadposition or gettailposition to retrieve the position of the chain header or the end of the chain table in the chain table. You can use the gethead or gettail function if you only want to get the linked list items at the head or end of the linked list. Because the position is already implicitly called, they do not need to enter the position value.
If the position value of a special linked list item is specified, you can use the at function of the linked list to retrieve, modify, or delete it:
Csting STR = List. getat (POS); // retrieve the item
List. setat (Pos, "Florida state"); // chage it
List. removeat (POS); // delete it
You can also use insertbefor or insertafter to insert linked list items in the linked list:
List. insertbefore (Pos, "Florida state ");
List. insertafter (Pos, "Florida state ");
The features of the linked list determine the efficiency of such insert and delete operations.
The linked list class of MFC also contains two member functions that can be used to perform the search operation. Findindex accepts the index number starting from 0 and returns the position value of the linked list item at the corresponding position in the linked list. Find finds the linked list item that matches the specified input and returns its position. For a string linked list, it compares a string to a pointer linked list, but does not look for or compare the linked list items referred to by the pointer. To search for "Tennessee" in the string linked list, you only need to call one function:
Position Pos = List. Find ("Tennessee"); by default, find searches for linked lists from the beginning to the end. If you want to, you can specify the start point of the search in the second parameter.
You can use the getcount function to understand the number of elements in the linked list. If getcount returns 0, the linked list is empty. The best way to detect an empty linked list is to call isempty.
2.2 create a "type security" linked list class with clist
You can use the clist class of MFC to create a secure linked list class for any selected data type. For example: clist <cpoint, cpoint &> list; like carray, the first parameter specifies the data type, the second parameter specifies the transfer method of the linked list items in the parameter list (by reference ).
If you use a class instead of the original data type in clist and call the find function of the linked list, the program will not be compiled unless one of the following conditions is true:
@ Class has the = Operator that is overloaded, and executes the comparison with similar objects
@ Override the template function compareelements with a special version and compare the two instances.
The first method is more commonly used. It has been implemented for you in MFC classes such as cpoint and cstring. If you write a class yourself, you must perform Operator overloading.
Overwrite compareelements to eliminate the need for overloaded operators.
4. Type pointer class
The names of the MFC collection classes with PTR and Ob (such as cptrarray, cobarray, cptrlist, and coblist) can be conveniently implemented to save the General pointer (void) and the container that saves the pointer to the MFC object (the object created by the cobject derived class. The problem with using PTR and ob classes is that they are too common. Many forced conversions are usually required, which is annoying for many c ++ programmers and is also a bad programming style.
The "type pointer class" of MFC is used to safely process pointer sets. It provides a simple solution to save pointers without compromising type security. The following "type security pointer class ":
Class Name Description
Ctypedptrarray manage pointer Array
Ctypedptrlist
Ctypedptrmap management uses pointers as a ing table for projects or keywords
Suppose you have compiled a drawing program and created a class named Cline to represent the line segments drawn on the screen. Each time a user draws a line, a new Cline object is created. If you need a place to save the Cline pointer and want to add or delete the pointer anywhere in the Set, the operation will not conflict, so you decide to use the linked list, because Cline is derived from cobject, coblist seems to be a natural choice.
Coblist can complete the task, but each time a cline pointer is retrieved from the linked list, it must be forcibly converted to Cline * Because coblist returns a cobject pointer. Ctypedlist is a good choice. It does not need to be converted forcibly. The Code is as follows:
Ctypedptrlist <coblist, Cline *> list;
When you use getnext to retrieve a cline pointer, you get a cline pointer without forced conversion. This is type security.
Like other "type security pointer classes", ctypedptrlist must be derived from "class specified by the first template parameter.
All the MFC collection classes that store pointers. They delete pointers from arrays, linked lists, or ing tables, but never delete the items that the pointers refer. Therefore, before clearing a cline pointer linked list, it is also necessary to delete the clines:
Position Pos = List. getheadposition ();
While (Pos! = NULL)
Delete list. getnext (POS );
List. removeall ();
Remember: if you do not delete clines, no one will delete it for you. Do not think that the collection class will do this for you.