C + + learning notes
01 basic grammar
#include<iostream> using namespace std; //Note: CTRL + K first, then CTRL + C //Uncomment: CTRL + K first, then CTRL + U int main() { cout << "hello world" << endl; system("pause"); return 0; }
02 sizeof
#include<iostream> #include<string> using namespace std; int main() { // Size of integer char number0 = 10; short number1 = 10; int number2 = 10; long number3 = 10; long long number4 = 10; cout << "char Memory occupied:" << sizeof(char) << endl; cout << "short Memory occupied:" << sizeof(short) << endl; cout << "int Memory occupied:" << sizeof(int) << endl; cout << "long Memory occupied:" << sizeof(long) << endl; cout << "long long Memory occupied:" << sizeof(long long) << endl; cout << "-----------------------------------------" <<endl; //Size of real type float number5 = 10.0; double number6 = 10.0; cout << "float Memory space size:" << sizeof(float) << endl; cout << "double Memory space size:" << sizeof(double) << endl; cout << "-----------------------------------------" << endl; //The size of the string char str1[] = "hello world"; //C-style string string str2 = "hello world"; //C + + style string cout << str1 <<"C The memory space size of the style string is:"<<sizeof(str1)<< endl; cout << str2 << "C++The memory space size of the style string is:" << sizeof(str2) << endl; cout << "-----------------------------------------" << endl; //Size of boolean type bool flag1 = true; bool flag2 = false; cout << flag1 << "Memory space size of Boolean quantity"<<sizeof(flag1) << endl; cout << flag2 << "Memory space size of Boolean quantity" << sizeof(flag2) << endl; cout << "-----------------------------------------" << endl; //Pointer size char* ptr = NULL; cout << "ptr Memory space size:" << sizeof(ptr) << endl; system("pause"); return 0; } //x86 output: /* char Memory space occupied: 1 short Memory space occupied: 2 int Memory space occupied: 4 long Memory space occupied: 4 long long Memory space occupied: 8 ---------------------------------------- - float Memory space size: 4 double Memory space size: 8 ---------------------------------------- - hello worldC Memory space size of style string: 12 hello worldC++Memory space size of style string: 28 ---------------------------------------- - 1 Boolean memory space size 1 0 Boolean memory space size 1 ---------------------------------------- - ptr Memory space size: 4 */ //x64 output: /* char Memory space occupied: 1 short Memory space occupied: 2 int Memory space occupied: 4 long Memory space occupied: 4 long long Memory space occupied: 8 ---------------------------------------- - float Memory space size: 4 double Memory space size: 8 ---------------------------------------- - hello worldC Memory space size of style string: 12 hello worldC++Memory space size of style string: 40 ---------------------------------------- - 1 Boolean memory space size 1 0 Boolean memory space size 1 ---------------------------------------- - ptr Memory space size: 8 */
03 machine level representation and operation of data
#include<iostream> #include<stdio.h> using namespace std; int main() { //Four arithmetic int a1 = 10; int b1 = 3; int c1 = a1 + b1; //The number of machines before and after strong rotation remains the same, but what changes is the way to interpret these bits cout << "2 The 32nd power of-1(All (1 yard)" << endl; unsigned u1 = 4294967295u; int tu = (int)u1; cout << "As an unsigned number, the complement code is the same as the original code. All 1 codes are equivalent to the 32nd power of 2-1,so v=" << u1 << endl; cout << "As a signed number interpretation, the highest bit of complement is negative weight, so uv=" << tu << endl; cout << "--------------------------------------------------------------------------------------------------------" << endl; int x = -1; unsigned u2 = 2147483648; //The 31st power of 2 (31 zeros after 1) printf("x = %u = %d\n", x, x); printf("u2 = %u = %d\n", u2, u2); //When performing an operation, if one operand is signed and the other is signed, the signed number will be implicitly converted to an unsigned number, and it is assumed that both numbers are non negative //Note that numbers like 1,2,3,0,-1,(int)1231u are signed numbers; //Numbers like (unsigned) - 1,-3u are unsigned cout <<"0 == 0u The results are:"<< (0 == 0u) << endl; cout << "-1<0 The results are:" << (-1 < 0) << endl; cout << "-1<0u The results are:" << (-1 < 0u) << endl; //-The machine code of 1 (all 1) will be interpreted as an unsigned number, so the result is abnormal system("pause"); return 0; }
04 array
#include<iostream> using namespace std; int main() { /*Three definition methods of one-dimensional array*/ //1. Data type array name [array length] int arr1[5]; //2. Data type array name [array length] = {value} int arr2[5] = { 1,2,3,4,5 }; //3. Data type array name [] = {value} int arr3[] = { 1,2,3,4,5, }; /*One dimensional array name can count the length of the entire array in memory*/ cout << "arr1 Memory space size" << sizeof(arr1) << endl; cout << "arr2 Memory space size" << sizeof(arr2) << endl; cout << "arr2[0]Memory space size" << sizeof(arr2[0]) << endl; cout << "--------------------" << endl; /*The array name is the first address*/ cout << "The first address of the array is:" << arr1 << "\t10 The hexadecimal form is:" << (int)arr1 << endl; cout << "The address of the first element of the array is:" << arr1[0] << "\t10 The hexadecimal form is:" << (int)arr1[0] << endl; cout << "--------------------" << endl; /*Array element inversion*/ cout << "Array element inversion" << endl; int start = 0; int end = sizeof(arr2) / sizeof(arr2[0]) - 1; while (start != end) { int temp = arr2[start]; arr2[start] = arr2[end]; arr2[end] = temp; start++; end--; } for (int i = 0; i < sizeof(arr2) / sizeof(arr2[0]); i++) { cout << arr2[i] << endl; } cout << "--------------------" << endl; /*Bubble sorting*/ cout << "Bubble sorting" << endl; int arr[] = { 4,2,8,0,5,7,1,3,9, }; cout << "Before sorting:" << endl; for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) { cout << arr[i] << endl; } //Compare adjacent elements, and if the first is larger than the second, swap the two of them //Perform the same work for each pair of adjacent elements. After execution, find the first maximum value //Repeat the above steps until the last pair is compared, that is, the number of rounds sorted = the number of elements - 1 for (int i = 0; i < sizeof(arr) / sizeof(arr[0]) - 1; i++) { for (int j = 0; j < sizeof(arr) / sizeof(arr[0]) - i - 1; j++) { if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } cout << "After sorting:" << endl; for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) { cout << arr[i] << endl; } cout << "--------------------" << endl; /*Definition of two-dimensional array*/ //1. Data type array name [number of rows] [number of columns]; int mat1[2][3]; //2. Data type array name [number of rows] [number of columns] = {data 1, data 2}, {data 3, data 4}; int mat2[2][3] = { {1,2,3},{4,5,6} }; //3. Data type array name [number of rows] [number of columns] = {data 1, data 2, data 3, data 4}; int mat3[2][3] = { 1,2,3,4,5,6 }; //4. Data type array name [] [number of columns] = {data 1, data 2, data 3, data 4}; int mat4[2][3] = { 1,2,3,4,5,6 }; /*Array name of two-dimensional array*/ //View the memory space size of a two-dimensional array cout << "The memory space size of two-dimensional array is:" << sizeof(mat1) << endl; //View the first address of a two-dimensional array cout << "The first address of the two-dimensional array is:" << mat1 << endl; system("pause"); return 0; }
05 function
#include<iostream> #include "sub file writing of function. h" using namespace std; //Function sub file writing int main() { long a = 10; long b = 20; long c = exchange(&a, b); cout << "c=" << c << endl; system("pause"); return 0; } //Definition of write function in source file long exchange(long* xp, long y) { long x = *xp; *xp = y; return x; }
Function sub file writing. h
#pragma once //Write the declaration of the function in the header file long exchange(long* xp, long y);
06 pointer
#include<iostream> using namespace std; int main() { /*Define pointer*/ int a = 10; int b = 20; int* ptr = &a; cout << "a Your address is:" << ptr << endl; /*Operation pointer*/ //You can find the memory pointed to by the pointer by dereferencing //A * in front of the pointer represents dereference *ptr = 1000; cout << "a The value of is:" << a << endl; cout << "*ptr The value of is:" << *ptr << endl; /*32 On 64 bit machines, the pointer occupies 4 bytes, and on 64 bit machines, the pointer occupies 8 bytes (selecting x86 or x64 above will have different results)*/ cout << "ptr Memory space size:" << sizeof(ptr) << endl; /*Null pointer*/ //Purpose: initialize pointer variables. Null pointers cannot be accessed //Note: memory numbers 0-255 are all memory occupied by the system and are not allowed to be accessed by users int* p1 = NULL; /*Field pointer*/ //int* p2 = (int*)0x1100; //Exception thrown: read access violation. //cout << *p2 << endl; /*const Modifier pointer*/ //1. Constant pointer (Understanding: since the pointer of a constant is a constant, of course, the value cannot be modified) const int* p3 = &a; //The pointer can be modified, but the value pointed to cannot be modified (* p = 20 illegal) p3 = &b; //legitimate //2. Pointer constant (Understanding: this pointer is a constant. Since it is a constant, of course, the pointer cannot be modified) int* const p4 = &a; //The pointer cannot be changed, and the value of the pointer can be changed (P4 = &b illegal) *p4 = 10; //3. const modifies both pointers and constants (Understanding: both are constants) const int* const p5 = &a; //Neither the pointer nor the value pointed to by the pointer can be modified system("pause"); return 0; }
07 pointers and arrays
#include<iostream> using namespace std; int main() { //Use pointers to access each element in the array int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int* ptr = arr; cout << "The first number of the array is:" << *ptr << endl; cout << "The first number of the array is:" << ptr[0] << endl; cout << "The first number of the array is:" << arr[0] << endl; cout << "The second number of the array is:" << ptr[1] << endl; cout << "The first number of the array is:" << arr[1] << endl; ptr++; cout << "The second number of the array is:" << *ptr << endl; system("pause"); return 0; }
08 pointers and functions
#include<iostream> using namespace std; void swap(int* a, int* b); void bubbleSort(int* arr, int len); int main() { //The pointer is used as a formal parameter to modify the value of the argument int a = 10; int b = 20; cout << "Before exchange"<< endl; cout << "a The value of is:" << a << endl; cout << "b The value of is:" << b << endl; swap(&a, &b); cout << "After exchange" << endl; cout << "a The value of is:" << a << endl; cout << "b The value of is:" << b << endl; //Using array, function and pointer to realize bubble sorting function int arr[10] = { 1,3,6,7,8,5,2,8,9,10 }; cout << "Before sorting" << endl; for (int i = 0; i < 10; i++) { cout << arr[i] << endl; } bubbleSort(arr, 10); cout << "Before and after sorting" << endl; for (int i = 0; i < 10; i++) { cout << arr[i] << endl; } system("pause"); return 0; } void swap(int* a, int* b) { //Exchange values after dereference int temp; temp = *a; *a = *b; *b = temp; } void bubbleSort(int* arr, int len) { for (int i = 0; i < len - 1; i++) { for (int j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j + 1]) { swap(&arr[j], &arr[j + 1]); //int temp = arr[j]; //arr[j] = arr[j + 1]; //arr[j + 1] = temp; } } } }
09 structure
Address book management system
#include<iostream> #include<string> #include<cstdlib> #define MAX 2000 using namespace std; //Address book management system //Design contact structure struct Person { string m_Name; int m_Sex; int m_Age; string m_Phone; string m_Addr; }; //Design address book structure struct Addressbooks { //Contact array saved in address book struct Person personArray[MAX]; //Number of contacts currently recorded in the address book int m_Size; }; //Add a Contact void addPerson(Addressbooks* abs) { //Full sentence if (abs->m_Size == MAX) { cout << "The address book is full" << endl; return; } else { //full name string name; cout << "Please enter your name" << endl; cin >> name; abs->personArray[abs->m_Size].m_Name = name; //Gender cout << "Please enter gender" << endl; cout << "1-male" << endl; cout << "2-female" << endl; int sex = 0; while (true) { cin >> sex; if (sex == 1 || sex == 2) { abs->personArray[abs->m_Size].m_Sex = sex; break; } cout << "Input error, re-enter" << endl; } //Age cout << "Please enter age" << endl; int age = 0; cin >> age; abs->personArray[abs->m_Size].m_Age = age; //Telephone cout << "Please enter phone number" << endl; string phone; cin>> phone; abs->personArray[abs->m_Size].m_Phone = phone; //address cout << "Please enter your address" << endl; string address; cin>> address; abs->personArray[abs->m_Size].m_Addr = address; //Number of contacts updated abs->m_Size++; cout << "Update succeeded" << endl; system("pause"); system("cls"); //Screen clearing operation } } //Show contacts void showPerson(Addressbooks* abs) { //Air judgment if (abs->m_Size == 0) { cout << "Current record is empty" << endl; } else { for (int i = 0; i < abs->m_Size; i++) { cout << "full name:" << abs->personArray[i].m_Name<<"\t"; cout << "Gender:" << (abs->personArray[i].m_Sex == 1 ? "male":"female")<< "\t"; cout << "Age:" << abs->personArray[i].m_Age << "\t"; cout << "Telephone:" << abs->personArray[i].m_Phone << "\t"; cout << "Address:" << abs->personArray[i].m_Addr << endl; } } system("pause"); system("cls"); //Screen clearing operation } //Check whether the contact exists int isExist(Addressbooks* abs, string name) { for (int i = 0; i < abs->m_Size; i++) { //User name found if (abs->personArray[i].m_Name == name) { return i; } } return -1; } //Delete Contact void deletePerson(Addressbooks* abs) { cout << "Please enter the contact to delete" << endl; string name; cin >> name; int ret = isExist(abs, name); if (ret != -1) { for (int i = ret; i < abs->m_Size; i++) { abs->personArray[i] = abs->personArray[i + 1]; } abs->m_Size--; cout << "Delete succeeded" << endl; } else { cout << "No one was found" << endl; } system("pause"); system("cls"); //Screen clearing operation } //find contact void findPersin(Addressbooks* abs) { cout << "Please enter the contact you want to find" << endl; string name; cin >> name; int ret = isExist(abs, name); if (ret != -1) { cout << "full name:" << abs->personArray[ret].m_Name << "\t"; cout << "Gender:" << (abs->personArray[ret].m_Sex == 1 ? "male" : "female") << "\t"; cout << "Age:" << abs->personArray[ret].m_Age << "\t"; cout << "Telephone:" << abs->personArray[ret].m_Phone << "\t"; cout << "Address:" << abs->personArray[ret].m_Addr << endl; } else { cout << "No one was found" << endl; } system("pause"); system("cls"); //Screen clearing operation } //Modify contact void modifyRerson(Addressbooks* abs) { cout << "Please enter the contact to modify" << endl; string name; cin >> name; int ret = isExist(abs, name); if (ret != -1) { //full name string name; cout << "Please enter your name" << endl; cin >> name; abs->personArray[ret].m_Name = name; //Age int age; cout << "Please enter age" << endl; cin >> age; abs->personArray[ret].m_Age = age; //Telephone int phone; cout << "Please enter phone number" << endl; cin >> phone; abs->personArray[ret].m_Phone = phone; //address string address; cout << "Please enter your address" << endl; cin >> address; abs->personArray[ret].m_Addr = address; cout << "Modified successfully" << endl; } else { cout << "No one was found" << endl; } system("pause"); system("cls"); //Screen clearing operation } //Empty contacts void cleanPerson(Addressbooks* abs) { abs->m_Size = 0; //Just set the number of contacts to 0 and clear them logically cout << "The address book has been emptied"<< endl; } //Menu interface void showMenu() { cout << "1. Add a Contact " << endl; cout << "2. Show contacts" << endl; cout << "3. Delete Contact " << endl; cout << "4. find contact " << endl; cout << "5. Modify contact" << endl; cout << "6. Empty contacts" << endl; cout << "0. Exit address book" << endl; } int main() { //Create address book Addressbooks abs; //Current number of people initializing the address book abs.m_Size = 0; int select = 0; //Create user selected input variables while (true) { // Menu interface showMenu(); cin >> select; switch (select) { case 1: //1. Add contact addPerson(&abs); //Modifying arguments using address passing break; case 2: //2. Display contacts showPerson(&abs); break; case 3: //3. Delete contact //{ // Cout < < please enter the name of the deleted contact: "< endl; // string name; // cin >> name; // if (isExist(&abs, name) == -1) { // Cout < < no one found < < endl; // } // else { // Cout < < find this person < < endl; // } //} deletePerson(&abs); break; case 4: //4. Find contacts findPersin(&abs); break; case 5: //5. Modify contact modifyRerson(&abs); break; case 6: //6. Empty contacts cleanPerson(&abs); break; case 0: //0. Exit address book cout << "Welcome to use next time" << endl; system("pause"); return 0; break; defult: break; } } system("pause"); return 0; }
10 global area
Memory partition model
When C + + programs are executed, they are roughly divided into four areas:
- Code area: the binary code of the function body, which is managed by the operating system
- Global area: stores global variables and constants
- Stack area: automatically allocated and released by the compiler to store parameter values and local variables of functions
- Heap area: it is allocated and released by the programmer. If the programmer does not release it, it will be recycled by the operating system at the end of the programmer
The meaning of memory 4 areas: different areas store different data and give different life cycles
1.1 before program operation
After the program is compiled, an exe executable program is generated. Before the program is executed, it is divided into two areas:
Code area:
-
Store machine instructions executed by CPU
-
The code area is shared. The purpose of sharing is to have only one code in memory for frequently executed programs (in essence)
-
The code area is read-only and its instructions are modified outside the program
Global area:
- Global and static variables
- The global area also contains the constant area, where string constants and other constants are stored
- This area is released by the operating system at the end of the program
#include<iostream> using namespace std; //global variable int g_a = 10; int g_b = 10; //const modified global variable, global constant const int c_g_a = 10; const int c_g_b = 10; int main() { //Global area //Global variable, static variable, constant //Ordinary local variable int a = 10; int b = 10; cout << "local variable a Your address is:" << (int)&a << endl; cout << "local variable b Your address is:" << (int)&b << endl; cout << "global variable a Your address is:" << (int)&g_a << endl; cout << "global variable b Your address is:" << (int)&g_b << endl; //Static variable (static) static int s_a = 10; static int s_b = 10; cout << "Static variable a Your address is:" << (int)&s_a << endl; cout << "Static variable b Your address is:" << (int)&s_b << endl; //constant //string constant cout << "The address of the string constant is:" << (int)&"hello world" << endl; //const modified global variable, global constant cout << "Global constant a Your address is:" << (int)&c_g_a << endl; cout << "Global constant b Your address is:" << (int)&c_g_b << endl; //const modified local variable, local constant const int c_l_a = 10; const int c_l_b = 10; cout << "Local constant a Your address is:" << (int)&c_l_a << endl; cout << "Local constant b Your address is:" << (int)&c_l_b << endl; system("pause"); return 0; }
Output:
local variable a The address of is 7274124 local variable b The address of is 7274120 global variable a The address of is 4726788 global variable b The address of is 4726792 Static variable a The address of is 4726796 Static variable b The address of is 4726800 The address of the string constant is 4755576 Global constant a The address of is 4755696 Global constant b The address of is 4755700 Local constant a The address of is 7274116 Local constant b The address of is 7274112
so
- Local variables and local constants are close together in the same area of memory
- Global variables, static variables, string constants and global constants are close together in the same area of memory
11 stack area
1.2 after program execution
Stack area:
-
The compiler automatically allocates, releases and stores the parameter values and local variables of the function
-
Note: do not return the address of local variables. The data opened up in the stack area is automatically released by the compiler
[Warning] address of local variable 'a' returned [-Wreturn-local-addr]
#include<iostream> using namespace std; //Stack area: automatically allocated and released by the compiler to store function parameter values, local variables, etc //Note: do not return the address of the local variable. The data opened up in the stack area is automatically released by the compiler int* func(int b) { //The formal parameter data will also be placed in the stack area b = 100; //Local variable: stored in the stack area. The data in the stack area is automatically released after the function is executed int a = 10; //Returns the address of a local variable (error) return &a; } int main() { int b = 0; int* p = func(b); cout << *p << endl; //The correct data can be printed for the first time because the compiler makes intelligent reservation cout << *p << endl; //The second time really can't get the correct result system("pause"); return 0; }
12 reactor area
Stacking area:
- It is distributed and released by the programmer. If the programmer does not release it, it will be recycled by the operating system after the program is completed
- In C + +, new and malloc are mainly used to open up memory in the heap area, and delete and free are used to release memory in the heap area
#include<iostream> using namespace std; //Heap area: it is allocated and released by the programmer. If the programmer does not release it, it will be recycled by the OS at the end of the program //In C + +, new is mainly used to open up memory in heap area int* func() { //new keyword, which can open up data to the heap //The pointer is essentially a local variable. It is placed on the stack, and the data pointed to by the pointer is placed on the heap int* p = new int(10); return p; } int main() { //Open up data in heap area int* p = func(); cout << *p << endl; cout << *p << endl; system("pause"); return 0; }
13 new operator
#include<iostream> using namespace std; //1. Basic syntax of new int* func() { //Create integer data in heap //new returns a pointer to the data type int* p = new int(10); return p; } //2. Open an array in the heap area void test02() { //Create a 10 integer array in the heap int*arr = new int[10]; for (int i = 0; i < 10; i++) { arr[i] = i; } for (int i = 0; i < 10; i++) { cout << arr[i] << endl; } //To release the heap array, add [] delete[] arr; } int main() { int* p = func(); cout << *p << endl; //The data in the heap area is managed by the programmer and released by the programmer cout << *p << endl; //delete for release delete p; //cout << *p << endl; (error will be reported) test02(); system("pause"); return 0; }
14 references
#include<iostream> using namespace std; //Exchange function //1. Value transfer void swap1(int a,int b) { int temp = a; a = b; b = temp; cout << "swap1 After formal parameter exchange a Value of:" << a << endl; cout << "swap1 After formal parameter exchange c Value of:" << b << endl; } //2. Address transfer void swap2(int* a,int* b) { int temp=*a; *a = *b; *b = temp; } //3. Reference transfer void swap3(int& a, int& b) { int temp = a; a = b; b = temp; } int main() { //The essence of reference: aliasing variables //Syntax: data type & alias = original name; //Notes for reference: //1. Reference must be initialized //2. The reference cannot be changed after initialization int a = 10; int& b = a; int c = 20; cout << a << endl; cout << b << endl; b = 100; cout << a << endl; cout << b << endl; //Reference as function parameter //Function: when passing a function parameter, you can use a reference to make the formal parameter as an argument //Advantages: simplify pointer modification arguments swap1(a, c); cout<<"swap1 After argument exchange a Value of:" << a << endl; cout<<"swap1 After argument exchange c Value of:" << c << endl; swap2(&a,&c); cout << "swap2 After argument exchange a Value of:" << a << endl; cout << "swap2 After argument exchange c Value of:" << c << endl; swap3(a, c); cout << "swap3 After argument exchange a Value of:" << a << endl; cout << "swap3 After argument exchange c Value of:" << c << endl; system("pause"); return 0; }
15 reference as return value of function
#include<iostream> using namespace std; //Reference as the return value of the function //1. Do not return references to local variables int& test1() { int a = 10; //Local variables are placed in the memory stack area return a; } //2. If the return value of the function is a reference, the call of the function can be used as an lvalue int& test2() { static int a = 10; //Static variables are stored in the global area, and the data in the global area is released by the OS after the program ends return a; } int main() { int& ret1 = test1(); cout << "ret1=" << ret1 << endl; //The compiler made a reservation for the first time cout << "ret1=" << ret1 << endl; //Second error int& ret2 = test2(); cout << "ret2=" << ret2 << endl; test2() = 1000; cout << "test2()After left value ret2=" << ret2 << endl; system("pause"); return 0; }
16 nature of reference
#include<iostream> using namespace std; //Essence: the implementation of a reference inside C + + is a pointer constant //Pointer constant: the pointer cannot be modified, and the value pointed to by the pointer can be modified void fun(int& ref) { ref = 100; } int main() { int a = 10; //Automatically convert to int * const ref = & A; //Because pointer constants point to immutable, references cannot be changed int& ref = a; ref = 20; //The compiler finds ref as a reference and automatically converts it to: * ref = 20; cout << "a:" << a << endl; cout << "ref:" << ref << endl; fun(a); cout << "a:" << a << endl; system("pause"); return 0; }
17 default parameters and placeholder parameters of function
#include<iostream> using namespace std; //Formal parameters can have default values //If you have passed in data, use your own data; otherwise, use the default value int fun1(int a, int b = 10, int c = 10) { return a + b + c; } //be careful: //1. If a location already has default parameters, it must have default values from left to right from this location //int fun2(int a, int b = 10, int c) { // C must have default parameters // return a + b + c; //} //2. If there is only one function declaration and function implementation with default parameters //int fun3(int a=10, int b=10); // //int fun3(int a = 10, int b = 10) { // error // return a + b; //} //Occupancy parameter void fun4(int a,int) { cout << "this is a fun" << endl; } int main() { cout << fun1(1) << endl; cout << fun1(1,20) << endl; cout << fun1(1, 20,20) << endl; //cout << fun3(10,10) << endl; fun4(10,10); system("pause"); return 0; }
18 function overloading
#include<iostream> using namespace std; //function overloading //Make the function name the same to improve the reusability of the function //Conditions for function overloading //1. Must be under the same scope //2. Same function name //3. Function parameters have different types, numbers, or orders //Note: the return value of a function cannot be used as a condition for function overloading void fun() { cout << "fun Call of()" << endl; } void fun(int a) { cout << "fun(int a)Call of" << endl; } void fun(double a) { cout << "fun(double a)Call of" << endl; } //Reference as overload condition void fun2(int &a) { cout << "fun(int &a)Call of" << endl; } void fun2(const int& a) { cout << "fun(const int& a)Call of" << endl; } //Function overload encountered default argument void fun3(int a) { cout << "fun3()Call of" << endl; } void fun3(int a,int b=10) { cout << "fun3(int a,int b=10)Call of" << endl; } int main() { int a = 10; fun(); fun(10); fun(10.1001); fun2(a); fun2(10); //fun3(10); // Error (ambiguous) system("pause"); return 0; }
19 classes and objects
#include<iostream> using namespace std; //Access rights //public: members can be accessed inside the class or outside the class //protected: members can be accessed inside the class, but not outside the class (subclasses can access the parent class) //private: members can be accessed inside the class, but not outside the class (subclasses cannot access the parent class) //private: member properties are generally privatized //public: functions (behaviors and methods) generally use global functions //Initialization and cleanup of objects: //Constructor: assign a value to the member attribute of the object when creating the object. The constructor is automatically called by the compiler without manual call //Destructor: automatically called by the system to perform some cleanup before the object is destroyed //Construction and deconstruction are necessary implementations. If we don't provide them ourselves, the compiler will provide the construction and Deconstruction of an empty implementation class Person { public: /*1. Constructor There is no return value and no need to write void The function name is the same as the class name Constructors can have parameters and can be overloaded When you create an object, the constructor is called automatically and only once */ //1.1 ordinary constructor: Person() { cout << "Person Call to the parameterless constructor of" << endl; } Person(int a) { age = a; cout << "Person Call to a parameterized constructor" << endl; } //1.2 copy constructor: //Initialize a new object with an already created object //The value transfer method is to transfer values to function parameters //Returns a local object as a value Person(const Person &p) { age = p.age; cout << "Person Call of copy constructor" << endl; } /*2. Destructor There is no return value and no need to write void The function name is the same as the class name, and it is added on the left~ Destructors cannot have parameters and cannot be overloaded The destructor is automatically called once and only once before the object is destroyed */ ~Person() { cout << "Person Call to destructor" << endl; } int age; }; //Call constructor void test01() { //1. Bracket method Person p1; //After test01() executes the data on the stack, release the object Person p2(10); Person p3(p2); //matters needing attention: //Call the default constructor without (), because the compiler will think it is the declaration of the function if () is added cout << "p2 Your age is:" << p2.age << endl; cout << "p3 Your age is:" << p3.age << endl; } void test02() { //2. Display method Person p1; Person p2 = Person(10); Person p3 = Person(p2); Person(10); //Anonymous object, features: after the execution of the current line, the system will immediately recycle the anonymous object //matters needing attention: //Do not use the copy constructor to initialize anonymous objects. Person(p3) === Person p3; Conflict with p3 above } void test03() { //3. Implicit method Person p4 = 10; //It is equivalent to writing Person p4 = Person(10); Person p5 = p4; //copy construction } int main() { //Constructors and destructors are called automatically test01(); test02(); test03(); system("pause"); return 0; }
20 deep copy shallow copy
Problems caused by shallow copy: create p1 object in heap area and construct p2 object by copy. After p2 calls destructor, if p1 calls destructor again, heap memory will be released repeatedly (illegal operation)
Solution: for deep copy, re apply for space in the heap area and perform the copy operation, so the heap area will not be released repeatedly
//Use deep copy solution to realize the copy constructor Person(const Person& p) { cout << "Person Copy constructor for" << endl; //m_Height = new int(height); The compiler executes this line of code by default m_Age = p.m_Age; m_Height = new int(*p.m_Height); } int* m_Height; int m_Age; };
Full code:
#include<iostream> using namespace std; //Shallow copy: a simple assignment copy operation //Deep copy: re apply for space in the heap area for copy operation class Person { public: Person() { cout << "Person Default constructor for" << endl; } Person(int age ,int height) { m_Height = new int(height); m_Age = age; cout << "Person Parameterized constructor for" << endl; } ~Person() { //Destructor: release the data opened up by the heap //Problem caused by shallow copy: heap memory is repeatedly released //if (m_Height != NULL) { // delete m_Height; // m_Height = NULL; //} cout << "Person Destructor for" << endl; } //Use deep copy solution to realize the copy constructor Person(const Person& p) { cout << "Person Copy constructor for" << endl; //m_Height = new int(height); The compiler executes this line of code by default m_Age = p.m_Age; m_Height = new int(*p.m_Height); } int* m_Height; int m_Age; }; void test01() { Person p1(18,160); cout << "p1 How old are you:" << p1.m_Age <<"p1 What is your height"<<*p1.m_Height << endl; Person p2(p1); cout << "p2 How old are you:" << p2.m_Age << "p1 What is your height" << *p2.m_Height << endl; } int main() { test01(); system("pause"); return 0; }
Output:
Person Parameterized constructor for p1 How old are you: 18 p1 What's your height: 160 Person Copy constructor for p2 How old are you: 18 p1 What's your height: 160 Person Destructor for Person Destructor for
The release of p1 and p2 no longer conflict! If the attribute is opened in the heap area, you must provide your own copy constructor to prevent problems caused by shallow copy
21 initialization list
#include<iostream> using namespace std; class Person { public: //Traditional initialization: //Person(int a, int b,int c) { // m_A = a; // m_B = b; // m_C = c; //} //Initialization list: Person(int a,int b,int c) : m_A(a), m_B(b), m_C(c) { } int m_A; int m_B; int m_C; }; void test01() { //Person p(10, 20, 30); Person p(10,20,30); cout << "m_A=" << p.m_A << endl; cout << "m_B=" << p.m_B << endl; cout << "m_C=" << p.m_C << endl; } int main() { test01(); system("pause"); return 0; }
22 class objects as class members
#include<iostream> #include<string> using namespace std; //Class objects as class members //Mobile phone class class Phone { public: Phone(string name) { cout << "Phone Constructor call for" << endl; m_PName = name; } string m_PName; ~Phone() { cout << "Phone Destructor call for" << endl; } }; //human beings class Person { public: Person(string name, string pName) : m_Name(name), m_Phone(pName) { cout << "Person Constructor call for" << endl; } ~Person() { cout << "Person Destructor call for" << endl; } string m_Name; Phone m_Phone; }; void test01() { Person p("123","123phone"); cout << p.m_Name << "Take:" << p.m_Phone.m_PName << endl; } int main() { test01(); system("pause"); return 0; }
Output:
Phone Constructor call for Person Constructor call for 123 Take it: 123 phone Person Destructor call for Phone Destructor call for
analysis:
When an object of another class is a member of this class, the object is constructed first and then itself
Similarly, release yourself first, and then release the object
23 static member variables
Class variables do not belong to an object. All objects share the same data. In the compilation stage, memory is allocated (allocated to the global area), declared within the class and initialized outside the class
#include<iostream> using namespace std; //Static member variable //Static member variables do not belong to an object, and all objects share the same data //Allocate memory at compile time (allocate to global area) //Inner class declaration, outer class initialization class Person { public: static int m_A; }; //Inner class declaration, outer class initialization //The '::' class scope operator. "::" indicates the class to which the member variable and function belong. For example, M::f(s) means that f (s) is a member function of class M. int Person::m_A = 100; void test01() { Person p1; cout << p1.m_A << endl; Person p2; p2.m_A = 200; //Note: still access with p1 cout << p1.m_A << endl; } void test02() { //Static member variables do not belong to an object, and all objects share the same data //Therefore, static member variables can be accessed in two ways //1. Access by object Person p; cout << p.m_A << endl; //2. Access by class name cout << Person::m_A << endl; } int main() { test01(); test02(); system("pause"); return 0; }
24 static member function
Class function. All objects share the same function. Static member functions can only access static member variables. Static member functions cannot access non static member variables because they cannot distinguish which object they belong to, and static member functions cannot be accessed outside the class
#include<iostream> using namespace std; //Static member function //All objects share the same function //Static member functions can only access static member variables class Person { public: //Static member function static void func() { m_A = 100; //Static member functions can only access static member variables //m_B = 100; // An error is reported. Static member functions cannot access non static member variables cout << "static void func()call" << endl; cout << "m_A= " << m_A << endl; } static int m_A; //Static member variable int m_B; //Non static member variable }; int Person::m_A = 0; void test01() { //1. Access by object Person p; p.func(); //2. Access by class name Person::func(); } int main() { test01(); system("pause"); return 0; }
Output:
static void func()call m_A= 100 static void func()call m_A= 100
All m in class_ A is modified to 100
25 member variables and member functions are stored separately
In C + +, member variables and member functions are stored separately
Only non static member variables are objects of a class
Empty object:
#include<iostream> using namespace std; class Person { }; int Person::m_B = 10; void test01() { Person p; //Memory occupied by empty object is 1 //Output: size of p = 1 //Analysis: the C + + compiler will allocate a byte space to each empty object to distinguish the memory occupied by empty objects //Each empty object also has a unique memory address cout << "size of p = " << sizeof(p) << endl; } int main() { test01(); system("pause"); return 0; }
Non empty object:
#include<iostream> using namespace std; class Person { int m_A; //Non static member variable static int m_B; //Static member variable void func() {} //Non static member function static void func2() {} //Static member function }; int Person::m_B = 10; void test02() { Person p; //Memory occupied by non empty objects is 1 //Output: size of p = 4 //Analysis: allocate memory according to the size of int //It is also proved that non static member variables belong to objects, //Static member variables do not belong to an object, so no memory is allocated for the object after it is created //Non static member functions are objects that do not belong to a class //Static member functions are also objects that do not belong to classes cout << "size of p = " << sizeof(p) << endl; } int main() { test02(); system("pause"); return 0; }
26 this pointer
Non static member functions will only produce one instance, and multiple objects of the same type will share the same piece of code. How to distinguish which member called itself?
C + + solves the above problem by providing a special object pointer, this pointer, which points to the object referred to by the called member function
Purpose of this pointer:
- When a formal parameter has the same name as a member variable, use the this pointer to distinguish it
- Return the object itself in the non static member function of the class. You can use return *this
#include<iostream> using namespace std; //1. Resolve name conflicts class Person { public: Person(int age) { //The this pointer points to the object p1 to which the called member function refers this->m_age = age; } //The returned ontology should be returned by reference //If it is a return value, after the first call to p2.PersonAddAge(p1), a new p2 'is copied and constructed. After each call, p2' 'is copied and constructed. return *this; It will not return p2 '' and so on, but only p2 called for the first time Person& PersonAddAge(Person& p) { this->m_age += p.m_age; //This is the pointer to p2, * this is the ontology pointing to p2 return *this; } int m_age; }; void test01() { Person p1(18); cout << "p1 Your age is:" << p1.m_age << endl; } //2. Use * this to return the object itself void test02() { Person p1(10); Person p2(10); //Chain programming idea: p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1); cout << "p2 Your age is: " << p2.m_age << endl; } int main() { test01(); test02(); system("pause"); return 0; }
27 null pointer access member function
#include<iostream> using namespace std; class Person { public: void showClassName() { cout << "whis is Person class" << endl; } //void showPersonAge() { // Error reason: the incoming pointer is null, and the member of the null object cannot be accessed // cout << "age is : " << this->m_age << endl; //} //Code robustness modification: void showPersonAge() { if (this == NULL) { return; } cout << "age is : " << this->m_age << endl; } int m_age; }; void test01() { Person* p = NULL; p->showClassName(); p->showPersonAge(); } int main() { test01(); system("pause"); return 0; }
28 const modifier member function
Constant function:
- Member functions plus const are called constant functions
- Member properties cannot be modified within a constant function
- After the keyword mutable is added to the member attribute declaration, it can still be modified in the constant function
Constant object:
- Add const before declaring the object as a constant object
- Constant objects can only call constant functions
#include<iostream> using namespace std; //1. Constant function class Person { public: //The essence of this pointer is a pointer constant, and the pointer cannot be modified //The value pointed to by this pointer can be modified //If you want the value pointed to by this pointer to be immutable, add a const before it //Therefore, add const after the function name and the member function to modify the this pointer. Since it is a modified pointer, the pointed value cannot be modified void showPerson() const { //this->m_ A = 100; // Cannot be modified this->m_B = 100; //Can be modified } void func() {} int m_A; mutable int m_B; //It can be modified even in constant functions }; void test01() { Person p; p.showPerson(); } //2. Common objects void test02() { const Person p; //Add const before the object to become a constant object //p.m_A = 100; // Cannot be modified p.m_B = 100; //Can be modified //Constant objects can only call constant functions //p.func(); // Ordinary member functions cannot be called because they can modify properties p.showPerson(); //Can call } int main() { test01(); test02(); system("pause"); return 0; }
29 global functions as friends
#include<iostream> using namespace std; //Buildings class Building { //The goodGay global function is a good friend of the Building class and can access private members in Building friend void goodGay(Building* building); public: Building() { m_SittingRoom = "a living room"; m_BedRoom = "bedroom"; } string m_SittingRoom; //a living room private: string m_BedRoom; //bedroom }; //Global function void goodGay(Building* building) { cout << "The global function of good friends is accessing:" << building->m_SittingRoom << endl; cout << "The global function of good friends is accessing:" << building->m_BedRoom << endl; } void test01() { Building building; goodGay(&building); } int main() { test01(); system("pause"); return 0; }
30 classes as friends
#include<iostream> #include<string> using namespace std; //Buildings class Building { //GoodGay is a good friend of this class and can access private members of this class friend class GoodGay; public: Building(); string m_SittingRoom; //a living room private: string m_BedRoom; //bedroom }; //Good friends //Class as friend class GoodGay { public: GoodGay(); void visit(); //Visiting functions to access properties in building Building* building; }; //Member functions implemented outside the class Building :: Building() { m_SittingRoom = "a living room"; m_BedRoom = "bedroom"; } GoodGay::GoodGay() { //Create a Building object building = new Building; } void GoodGay::visit() { cout << "Good friends are visiting: " << building->m_SittingRoom << endl; cout << "Good friends are visiting: " << building->m_BedRoom << endl; } void test01() { GoodGay gg; gg.visit(); } int main() { test01(); system("pause"); return 0; }
31 member function as friend
#include<iostream> #include<string> using namespace std; //Declare the building class first, and no error will be reported class Building; //Good friends class GoodGay { public: GoodGay(); void visit(); //Let the visit function access private members in Building void visit2(); //Make the visit2 function inaccessible to private members in Building Building* building; }; //After that, you can define the Building class, because compile friend void GoodGay::visit(); The premise is that the definition of GoodGay class is known, so class Building must be declared first; Define the Building class after the definition of the base friend class is completed class Building { //Tell the compiler that the member function under GoodGay class, as a good friend of this class, can access private members friend void GoodGay::visit(); public: Building(); string m_SittingRoom; //a living room private: string m_BedRoom; //bedroom }; //Member functions implemented outside the class Building::Building() { m_SittingRoom = "a living room"; m_BedRoom = "bedroom"; } GoodGay::GoodGay() { //Create a Building object building = new Building; } void GoodGay::visit() { cout << "Good friends are visiting: " << building->m_SittingRoom << endl; cout << "Good friends are visiting: " << building->m_BedRoom << endl; } void GoodGay::visit2() { cout << "Good friends are visiting: " << building->m_SittingRoom << endl; //Cout < < good friends are visiting: "< building - > m_ BedRoom << endl; } void test01() { GoodGay gg; gg.visit(); gg.visit2(); } int main() { test01(); system("pause"); return 0; }