string
Source code:
void test(int n) { // Sample test, test the function of initializing string object string str1 = "hello"; string str2 = "hello123"; string str3 = "hello123456"; string str4 = "hello123456789"; string str5 = "hello123456789123"; string str6 = "hello123456789123456"; string str7 = "hello123456789123456789"; } int main() { int n = 1; scanf_s("%d", &n); test(n); }
Disassembly view
Now we put ecx in the data window and find that it is filled with CC
Address after calling constructor Let's see 00ab560 is the four bytes of the first address of a string
When we came over, we found it was a heap space Two data (FD is the end of the heap) 0059f880 find that it points to the address of our string, so it may be more convenient for him to find himself
Let's go on
The length of this string is 0E and the maximum buffer is 0f
If we continue to expand our string, how will string store our string???
The length of our string is 11 and the maximum number of bytes stored in the buffer is 1F. The main reason is that the second field is no longer our string and becomes an address
Let's go over and save our string
So you can define the following structure
struct MyString { struct MyString* pSelf; union MyUnion { char szString[16]; char* pString; }u; int nStringLen; int nMaxStringLen; }; //Define this structure pointer to operate on it string str1 = "hello"; MyString* pString = (MyString*)&str1; strcpy(pString->u.szString, "hello"); pString->nStringLen = 9;
CString
It's relatively simple
His object has only four bytes.
Is a pointer to the heap space, where strings are stored. Too simple to look at disassembly
Come and see our string
list
void testList() { // Bidirectional circular linked list, node list<int> listObj; listObj.push_back(1); listObj.push_back(2); listObj.push_back(3); listObj.pop_back(); listObj.push_back(4); }
First initialization after calling the initialization function
The list container calls the initialization function twice Zero for the first time, and there will be data for the second time
Address after two initialization
Then push_back a data to see the change
The number of elements becomes 1. Next, let's look at 00e9cd98 the address of the header of the linked list
A total of two elements are the precursor and successor of the linked list We see that the precursors and successors of the linked list point to one place because we have only one element. It can be seen that this is a two-way circular linked list
Because adding an element doesn't look good, let's add one
Look, there are two elements in memory, namely, push_back 1 and 2 of
The position of the header is now different from that of the predecessor and successor
We continued to look along the linked list
Or the predecessor and successor
2 is our data Continue backward
It's our data 1. The front is still the predecessor and successor
Continue back to our header
So the structure is like this
Therefore, the following structure can be defined
struct MyNode { struct MyNode* pNext; struct MyNode* pPrev; int nData; }; struct MyList { struct MyList* pSelf; struct MyNode* pRoot; int nNodeCount; }; MyList* pList = (MyList*)&listObj; int size = pList->nNodeCount; MyNode* pNode = pList->pRoot; while (pNode->pNext != pList->pRoot) { pNode = pNode->pNext; int n = pNode->nData; printf("element=%d\n", n); }
Vector
void testVector() { // Dynamic array, data stored in heap memory // When the element changes, the memory will be increased dynamically. vector<int> vecObj; vecObj.push_back(1); vecObj.push_back(2); vecObj.push_back(3); vecObj.pop_back(); vecObj.push_back(4); vecObj.push_back(5); vecObj.push_back(6); vecObj.push_back(7); //------------------------------------- // Traverse vector for (size_t i = 0; i < vecObj.size(); i++) { printf("vecObj[%d] = %d", i, vecObj[i]); } //------------------------------------- // Traverse vector vector<int>::iterator iter = vecObj.begin(); while (iter != vecObj.end()) { int n = *iter; printf("vecObj i = %d", n); iter++; // Temporary object generation //++iter;// No temporary objects } }
The second initialization will fill in the pointer to itself
push_back has two elements
The first is a pointer to yourself
The second is a pointer to the buffer
The third is a pointer to the last byte of the element
The fourth is a pointer to the last byte of the requested buffer
0134e148 is the first two elements 1 and 2 of the array address The last two pointers in the figure above point to the position of FD
Add a data in
After adding a data, it is found that the buffer used to put the data has been released
The buffer for the second field of our dynamic array has also changed position
We can guess that in push_back, dynamically apply for new space and copy the data.
If the space is insufficient, apply for a new and larger space and copy the original data in.
Pop is executed again_ back
We see that the pointer to the last element of the array has changed because there are fewer array elements
In fact, the data is still there, but it changes the pointer, that is, the valid data are 1 and 2
Continue to add 4 5 6 7
For the current dynamic array structure, let's look at the location where 0134F4E8 stores data
The last two pointers in the figure above point to the last byte of the valid element and the last byte of the valid buffer respectively
The structure is like this
You can define this structure
struct MyVector { struct MyVector* pSelf; int* pDataStart; int* pDataEnd; int* pBufEnd; }; // Define structure, operate vector MyVector* pVector = (MyVector*)&vecObj; int size = ((int)pVector->pDataEnd - (int)pVector->pDataStart) / sizeof(int); for (size_t i = 0; i < size; i++) { //pVector->pDataStart[i] = 3; int n = pVector->pDataStart[i]; printf("element=%d\n", n); }
Next, let's look at the traversal dynamic array. We look at the source code. It will call three functions, one is size, and the other is [] operation symbol overload
There is also a printf ordinary loop traversal
// Traverse vector for (size_t i = 0; i < vecObj.size(); i++) { printf("vecObj[%d] = %d", i, vecObj[i]); }
Next, look at iterator traversal
//------------------------------------- // Traverse vector vector<int>::iterator iter = vecObj.begin(); while (iter != vecObj.end()) { int n = *iter; printf("vecObj i = %d", n); iter++; // Temporary object generation //++iter;// No temporary objects }
Twice initialization Let's look at memory
0134E0E0 points to two four byte data
The first four bytes point to the address of the vector
The second four bytes point to itself
00000000 useless
0134f4e8 points to the buffer where the data is stored
Let's go to 0134e0e0 and have a look
Let's look at 0134F4E8, which is the data we store
So the structure is like this