[C + + Notes] IV. complex data types

Posted by ctiberg on Fri, 21 Jan 2022 19:59:04 +0100

catalogue

18. Pointer Foundation

18.1} what is stored in the variable

18.2 how to use variables in programs

19. Pointer movement and data type

20. Pointer initialization

21. Use the new keyword to allocate memory space

22. Use delete to free memory space

23. Dynamically create and release arrays

24. Use dynamically created arrays

25. Pointer and string

26. Constant pointer and pointer constant

26.1 constant pointer

26.2 pointer constants

27. Use new to dynamically create a structure

28. Use new to dynamically create a common body

29. Multi dimensional array and multi-level pointer

29.1 multidimensional array

29.2 multi level pointer

30.vector template class foundation

31. Array template

The difference between array and array template

18. Pointer Foundation

18.1} what is stored in the variable

Variables are stored in memory space.

int n = 100;
float value = 123.321;

cout << "n = " << n << endl;    // 100 
cout << "n address = " << &n << endl;   // 0x7fff5fbffb4c each hexadecimal number represents a 4-bit binary number
/* In fact, for a 64 bit system, the address should be 64 bit binary, that is, 8 bytes, and the full version of the address should be 0x00007fff5fbffb4c, except that the previous zeros are omitted*/
// That is, 16 bit hexadecimal < = = > 64 bit binary, and two bit hexadecimal number (corresponding to 8-bit binary number) represents 1 byte
/* Note: 1-bit hexadecimal number is different from 16 bit binary number. 1-bit hexadecimal number corresponds to 4-bit binary number, which is a half byte, and 16 bit binary corresponds to 2 bytes */

// For 32-bit systems, the address should be 32-bit binary, corresponding to 4 bytes

cout << "value = " << value << endl;   // 123.321
cout << "value address = " << &value << endl;   // 0x7fff5fbffb28, the preceding 0000 is omitted
 //Error report: long type and pointer type occupy the same space, but they cannot be assigned directly
long pointer  = &value; 

long pointer  = long(&value); 
cout << "pointer = " << pointer << endl;//The decimal number 140734799805208 is the decimal version of the hexadecimal address value

18.2 how to use variables in programs

// Purpose of pointer
int abc[10] = {1};   // Save up to 10
abc[123] = 3;    // The memory is exceeded, but it is allowed in C + +, but it may crash the program

int abc[200] = {1};   // This can prevent the program from crashing, but it wastes memory. Pointers can solve this problem
abc[123] = 3;    

int *pn = &n;    // Define pointer variables
float *pvalue = &value;  // Defines a pointer to a variable of type float

cout << "pn = " << pn << endl;   // Output address in hexadecimal mode
cout << "pvalue = " << pvalue << endl;
    
cout << "*pn = " << *pn << endl;    // 100
cout << "*pvalue = " << *pvalue << endl;     // 123.321

cout << sizeof(*pn) << endl;    //  4

//Pointer itself is a value of long type, which can be cast to pointer type through (float *)
cout << "*pvalue = " << *((float*)pointer) << endl;   // 123.321

19. Pointer movement and data type

int numbers[2] {25,26};
// int *numbers;  The default is to point to the first number of the array: numbers[0], numbers[1]

cout << "numbers[0]=" << *numbers << endl;  // 25 
cout << "numbers[1]=" << *(numbers+1) << endl;  // 26

char chars[2] {25, 26};     
cout << "chars[0]=" << int(*chars) << endl;     //  25
cout << "chars[1]=" << int(*(chars+1)) << endl;  //   26

void *p = numbers;
cout << "chars[1]=" << int(*(p+1)) << endl;  // report errors

25 corresponding binary: 11001

26 corresponding binary: 11010

Variables of type int occupy 4 bytes in memory, 8 bits per byte, a total of 32 bits. char type variables occupy 1 byte in memory,

When pointing to a variable of type int + 1, the pointer moves 4 bytes; when pointing to a variable of type char + 1, the pointer moves 1 byte

void *p = numbers;
cout << "chars[1]=" << int(*(p+1)) << endl;  // report errors

Because the pointer points to void Type. This is an uncertain type. The pointer does not know how many bits to move, so an error will be reported
 If you want to move the pointer, you need to specify the data type pointed to by the pointer

20. Pointer initialization

int xyz = 30;
int *p;
cout << "p address=" << p << endl; // Print 0x0

int xyz = 30;
int *p = &xyz;
cout << "p address=" << p << endl;  // 0x7fff5fbffb4c

p = &xyz;    
*p = 123;
    
cout << "xyz = " << xyz << endl;   // 123
    
xyz = 456;
cout << "*p = " << *p << endl;    //  456

21. Use the new keyword to allocate memory space

int xyz = 100;  
int *p = &xyz;    // Initializing the pointer also requires a separate variable to be defined, which is relatively troublesome

// In C language, malloc can be used to allocate memory space. C + + can also be used, but new is better
// typename *pointer = new typename
int *pointer = new int;  // A 4-byte memory space is allocated, and the first address of the memory space is assigned to the pointer
*pointer = 123;
cout << "*pointer=" << *pointer << endl;   // 123

// distinguish:
int xyz = 100;   // 4 bytes of memory space is allocated, and the memory space is named xyz
int *pointer = new int;     /* The allocated memory space is not named, so the memory space allocated by new cannot be used by name. The only way to use the memory space is to use the pointer pointing to the first address of the memory space. Pointer is the name of the first address of the memory space, and xyz is the name of the whole memory space  */

double *value  = new double;
*value = 33.22;
cout << "*value=" << *value << endl;  // 33.22

// If new fails to allocate memory space, an exception will be thrown

22. Use delete to free memory space

/*
  1.  delete Only the memory space allocated with new can be released, and the memory space allocated with malloc and similar functions cannot be released
  2.  The common variable system will automatically reclaim the occupied memory space, but the system will not automatically reclaim the dynamically allocated memory space (on the heap) such as new and malloc
  3.  delete After that, the data of the pointer itself and the memory space pointed to by the pointer will not be cleared unless the data is written again
  4.  Multiple pointers point to the same memory space. As long as one pointer is released, the others will be released
  5.  The memory space pointed to by the pointer that has been released cannot be released again.
*/

int *n = new int;
*n = 123;
cout << "n address before delete:" << n << endl;   // 0x100103a40

// 1 2
delete n;  // No*
int xyz = 300;

cout << "n address after delete:" << n << endl;  // 0x100103a40
cout << "n = " << *n << endl;   // 123

// 3
// When using new to dynamically allocate memory space, a flag will be given on the memory space, indicating that the memory space will not be allocated to any other variables. Using delete means that the flag is cleared, and the memory space may be allocated to other variables at any time
*n = 456;  /* Try not to use it like this. Although the data in this memory space is still there, the space has been released and may be occupied by other variables at any time */ 
cout << "n = " << *n << endl;   // 456

int xyz = 300;
n = &xyz;  // There is no problem with this, because xyz is on the stack

// 4
int *m = new int;
*m = 444;
int *p = m;   // p and m point to the same memory space with a length of 4 bytes
delete p;  // Equivalent to releasing m

// 5
delete p;  //  Throw exception  
delete  m;   //  Throw exception

23. Dynamically create and release arrays

int n = 20;
int array1[10];   // The array length needs to be specified when defining
int array2[n];

int *array3 = new int[n];
int *array4;

array4 = new int[100];
//array4 = new int[200];  /*  This will cause memory leakage because new int[100]; If the memory space of is not released, a new space is defined, which will result in that the original 400 bytes of memory space will not be allocated to any variables. Even if the program exits, the memory space will not be released*/

delete [] array4;
// array4 = new int[200] / / no problem

  // array4 = NULL;  // 0, set the pointer variable / array to null, and you'd better add this after delete
array4 = nullptr;  // Try to use nullptr instead of NULL in c++ 11
int *p = new int;
delete p;
p = nullptr;   // It is best to set the pointer to null after delete
array4 = new int[200];

24. Use dynamically created arrays

int *array = new int[10]{1,2};  // Allocated space to store 10 int type values, and initialized the first two array elements
array[2] = 30; // You can also assign a value to an array element separately
array[3] = 50;

cout << "array[0]=" << array[0] << endl;  // 1
cout << "array[3]=" << array[3] << endl;  // 50

// Reference array elements using pointers
cout << "array[2]=" << *(array + 2) << endl;  // 30

int codeArray[3]{10,20, 30};
cout << "codeArray[0] = " << codeArray[0] << endl;   // 10
cout << "codeArray[1] = " << *(codeArray + 1) << endl;  // 20
cout << "codeArray[2] = " << *(codeArray + 2) << endl;   // 30
    
array++;
cout << "array[1]=" << *array << endl; // 2
array--; // It also refers back to the first address of the storage space

codeArray++;  // An error is reported, which is not allowed. For non pointer arrays, self addition or self subtraction cannot be used

// Free memory space for array
delete [] array;
array = nullptr; 

25. Pointer and string

char str[10] = "hello";  // String defined
cout << str << endl;   // hello

int pp = 3;
char *p_str = "hello"; //This definition is not recommended. It is equivalent to a string pointer to a constant character. Each character cannot be modified
cout << p_str << endl;  // hello

char *p = str;    // p points to str. if STR is modified, p will also be modified
cout << p << endl;   /* Print the hello. Note that the address of h is not output here, but the whole hello. Because the I/O class in the C + + standard library overloads the < < operator, it will be treated as a string name when encountering a character pointer, and the string referred to by the pointer will be output */

p = new char[strlen(str) + 1];   // Allocate a space for the string terminator
strcpy(p, str);    /* The function will automatically add an end character. The first parameter is the first address of the target memory space, and the second parameter is the address of the content to be copied */
    
str[1] = 'x';
cout << str << endl;    // hxllo

*(p + 2) = 'w';   // p refers to the new memory space. After str is modified, p will not be affected
cout << p << endl;    //  hewlo

char *p_str = "hello"; //It is equivalent to a string pointer pointing to constant characters. Each character cannot be modified. This is not recommended
*p_str = 's';   // report errors

delete [] p;
delete [] p_str;  // An error is reported. delete [] can only free the memory space allocated by new

26. Constant pointer and pointer constant

26.1 constant pointer

//  const pointer 
const int code = 1234;  //  Constants must be initialized when defined
// code = 3;  //   An error is reported and cannot be changed. The constant is allocated on the stack. It is read-only and cannot be changed
const int numbers[] = {1,2,3,4};
//  numbers[2] = 44;  //  report errors

const int *p = new int(100); // Constant pointers are usually initialized at declaration time
// *p = 333;  //  An error is reported. The constant pointer points to a constant. It is not allowed to change the value it points to through this pointer
cout << *p << endl;
    
char str[10] = "hello";
const char *p_str = str;  // A constant pointer to a string does not allow characters to be modified
// str can be changed, but * p_str cannot be changed
//*p_str = 'a';   //  Error report, p_str is a constant pointer. It is not allowed to change the value it points to through this pointer

26.2 pointer constants

char * const p_str1 = str;
*p_str1 = '1';    // Can change
p_str1 = new char[3];   // An error is reported. The pointer cannot point to the new memory space

const char * const p_str1 = str;
*p_str1 = '1';    // report errors
p_str1 = new char[3];   // An error is reported. The pointer cannot point to the new memory space

27. Use new to dynamically create a structure

#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
//  Create structure object ① ② with new 

    struct MyStruct
    {
        int code;
        char *name;
        double price;
    };
    
    MyStruct *p = new MyStruct();   

    // Use '- >' when accessing structure members with structure pointers    
    p->name = "abc";  /* An error is reported. Name itself is a character pointer, so new MyStruct() only allocates pointer sized memory to name. The memory pointed to by name has not been allocated, so it is necessary to allocate memory to the place pointed to by name */ 
    p->name = new char[30];   // A total of 30 character size / type data can be stored, ②
    
    strcpy(p->name, "iPhone6 plus 256G");
    
    (*p).code = 1234;   // Another way to access members using structure pointers
    
    p->price = 9999;
    
    cout << "p->name = " << p->name << endl;   // iPhone6 plus 256G
    cout << "(*p).code = " << (*p).code << endl;   // 1234
    cout << "p->price = " << p->price << endl;     // 9999

    return 0;
}

28. Use new to dynamically create a common body

union MyUnion
{
     int code1;
     long code2;
};
    
MyUnion *p = new MyUnion();   //  Using new to dynamically create a common body
p->code1 = 200;
cout << "p->code1 = " << (*p).code1 << endl;  // 200
cout << "p->code2 = " << (*p).code2 << endl;  // 200
    
(*p).code2 = 400;
cout << "p->code1 = " << p->code1 << endl;   /* 400,As long as the number set is less than the range of int, code1 and code2 are equal */

29. Multi dimensional array and multi-level pointer

29.1 multidimensional array

int codes1[10] = {1,2,3};  // One dimensional array


int codes2[5][10];   // Two dimensional array

/*
Use a one-dimensional array to represent a two-dimensional array: find the index of codes1[8] in codes2[5][10]:
Rounding calculation row index rounding calculation column index: 8 / 5 = 1 (row 2, index starts from 0) 8% 5 = 3 (column 4, index starts from 0). Therefore, the two-dimensional array index corresponding to codes1[8] is codes1[1][3]
Calculate one-dimensional array index from two-dimensional array: codes1 [1] [2] 1 * 5 + 2 = 7 = codes1 [7]
*/
// One dimensional array initialization method: the first element in the second row of initialization is 123
int codes2[5][10] = {1,2,3,4,5,6,7,8,9,0,123/*codes2[1][0]*/};  // The first ten have to "run with me", which is very troublesome
cout << "codes2[1][0] = " << codes2[1][0] << endl;   //  123

// Initialization method of two-dimensional array - initialize the 10th element in line 5 to 200
int codes2[5][10] =  {{1,2},{4,5},{},{},{1,2,3,4,5,6,7,8,9,200}};
cout << "codes2[4][9] = " << codes2[4][9] << endl;  // 200

// The three-dimensional array initializes five channels, 10 rows and 100 columns, that is, five 10x100 two-dimensional arrays
int codes3[5][10][100] = {{{1,2}/*The first two column elements (100 columns in total) of the first row of the first channel of codes3 are initialized, codes3[0][0] [...]*/,{4,5}/*The first two column elements (100 columns in total) of the second row of the first channel of codes3 are initialized, codes3[0][1] [...]*/},{}/*Changed channels codes3[1] [...]*/};
cout << "codes3[0][0][1] = " << codes3[0][0][1] << endl;    // 2 elements in the first row and the second column of the first channel
cout << "codes3[0][1][0] = " << codes3[0][1][0] << endl;    // 4 elements in the first channel, the second row and the first column

// Sets the value of the array
codes1[0] = 123;
codes2[0][0] = 445;
codes3[0][0][2] = 234;

29.2 multi level pointer

int codes1[10] = {1,2,3};  // One dimensional array
int codes2[5][10] =  {{1,2},{4,5},{},{},{1,2,3,4,5,6,7,8,9,200}};
int codes3[5][10][100] = {{{1,2},{4,5}},{}};

int *p1 = codes1; // The single pointer p1 stores the address, and the memory space pointed to by the address stores the int value
// int **pp2  = codes2;  //  report errors
int **pp2  = (int**)codes2;//Double pointer, pp2 stores the address, and the memory pointed to by the address stores the pointer (also the address)
// cout << pp2[2][3] << endl;  //  report errors

int *pp1 = new int;   // no problem
// int **pp2 = new int[10][10] / * an error is reported. This sentence only assigns a value to pp2 and does not create a new memory space for the contents of pp2*/

int **ppp2 = (int**)new int[10][10];  
// **ppp2 = 3;   //  report errors

int* xyz[10];     // The elements in the array are pointers to int values
// *xyz[0] = 3;   //  If an error is reported, write a value to the memory space pointed to by the first pointer of XYZ array

int* xyz[10]; 
xyz[0] = new int;  // To allocate memory space where the first pointer points
*xyz[0] = 3;       // correct

int **pppp2 = new int*[10];    // Normally, allocate memory space with a length of 10 int * for the secondary pointer
for(int i =0; i < 10;i++)
{
    *(pppp2+i) = new int[10]; // Allocate memory space with a length of 10 ints for each element (int *)
}
    
**pppp2 = 203;   // correct

**(pppp2 + 1) = 100;   //Add one to the secondary pointer, indicating that the line is added one, which is moved down one line; How to get 100 by array?
cout << "**(pppp2 + 1) = " << pppp2[0][1] << endl;   // 0, not 100
cout << "**(pppp2 + 1) = " << pppp2[1][0] << endl;   // 100

30.vector template class foundation

#include <iostream>
#Include < vector > / / declare library functions
using namespace std;

int main(int argc, const char * argv[])
{
    //  The vector template class can be regarded as a dynamic array
    //  Can be used as an array or stack

    vector<int> values;   // Elements in vector can only store int type values, and values is a vector type variable

    //  Add three elements dynamically
    values.push_back(20);    // first
    values.push_back(40);    // the second
    values.push_back(60);    // Third
    
    for(int n:values)    // Enumerate all elements in value
    {
        cout << n << endl;     // 20 40 60
    }

    // Deletes the specified element
    // values.pop_back();  //  Out of the stack, delete the last element, and 60 is gone
    //values.erase(values.begin());  //   Delete the first element, 20 is gone
    values.erase(values.begin() + 1);  //  Delete the second element, 40 is gone

    // Get vector size
    long size = values.size();
    cout << "values size = " << size << endl;   // 2 elements, not 2 bytes
    for(long i = size - 1; i>=0;i--)   // Enumerate the values in the vector variable in reverse order by array
    {
        cout << values[i] << endl;   // 60  20
    }
    cout << values.at(0) << endl;    // 20. Utilization at index the elements in the array
    
    return 0;
}

31. Array template

The difference between array and array template

  1. Array and array template are different in late initialization
  2. Variables are allowed for the size of the array, but variables are not allowed for the size of the array template, but constants or numeric values can be used
  3. Arrays can be used as pointers to some extent, but array templates cannot
  4. The array template makes it easier to get the size of the array (with. size())
  5. Assigning an array to a pointer is a reference copy, and the assignment between array templates is a value copy

Note: neither the array nor the array template should exceed the maximum index

#include <iostream>
#Include < array > / / declaration
using namespace std;
int main(int argc, const char * argv[]) {
    array<string, 5> productNames = {"iPhone6", "iPhone6 Plus"};

    array<int,3> codes;
    codes = {200,300,400};  // Array templates can be defined first and then initialized as a whole
    
    int codes1[3]; //If an ordinary array is not initialized at the time of definition, it can only be initialized for a single element, not the whole
    codes1[0] = 200;   // no problem
    //  codes1 = {1,2,3};  //   syntax error
    
    int n = 100;     // variable
    int codes1[n];   // Variables can be used to define array sizes

    const int size = 3;   // constant
    // int size = 3;     //  An error will be reported at the array template
    array<int,size> codes;
    codes = {200,300,400};  
    
    cout << "productNames[0] = " << productNames[0] << endl;

    // The index method of array template is the same as that of array
    if(productNames[4] == "")
    {
        cout << "productNames[4]uninitialized" << endl;
    }
    
    cout << "codes[2] = " << codes[2] << endl;

    int abc[3] = {1,2,3};
    cout << "abc[0] = " << *abc << endl;  /* 1 ,Arrays and pointers are common to some extent. When you value the array name, you will get the value of the first element  */
    
    cout << "productNames size is " << productNames.size() << endl;  /* Print the size of the array template (number of elements) */
    cout << "abc size is " << sizeof(abc)/sizeof(int) << endl;  /* Print the size of the array (number of elements) */
    
    //abc[5] = 3;   //  No error is reported, and the C + + compiler does not detect boundaries
    // productNames[10] = 4;  //  No error is reported, but the output may be garbled
    // cout << "productNames[10] = " << productNames[10] << endl;  //  The output is garbled

    //   Enumerate elements in an array template
    for(int i = 0;i < 2;i++)
    {
        cout << productNames[i] << endl;   // iPhone6   iPhone6 Plus
    }
    
    for(int value:codes)
    {
        cout << value << endl;    // 200 300 400
    }

    // Assignment of array template  
    array<int , 3> codes1;
    codes1 = codes;    // This is a value assignment, not a reference assignment, so changing codes1 will not affect codes
    codes1[0] = 123;
    
    cout << "codes1[0] = " << codes1[0] << endl;   //  123
    cout << "codes[0] = " << codes[0] << endl;     //  200
    
    int codes2[]{1,2,3};
    // int codes3[] = codes2;  //  Syntax does not allow direct assignment between arrays
    int *pCodes = codes2;    // A pointer can be used to copy a reference
    pCodes[0] = 321;    // The value of codes2 will also change
    cout << "codes2[0] = " << codes2[0] << endl;   // 321
    
    return 0;
}

Topics: C++