C + + learning notes

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:

  1. Store machine instructions executed by CPU

  2. The code area is shared. The purpose of sharing is to have only one code in memory for frequently executed programs (in essence)

  3. The code area is read-only and its instructions are modified outside the program

Global area:

  1. Global and static variables
  2. The global area also contains the constant area, where string constants and other constants are stored
  3. 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:

  1. The compiler automatically allocates, releases and stores the parameter values and local variables of the function

  2. 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:

  1. 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
  2. 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;
}

Keywords: C++

Added by Joost on Tue, 21 Sep 2021 06:26:11 +0300