C + + learning record (memory model and reference of program)

1 memory partition model

During the execution of C + + program, the general direction of memory is divided into four areas

  • Code area: it stores the binary code of the function body and is managed by the operating system
  • Global area: stores global variables, static variables and constants
  • Stack area: automatically allocated and released by the compiler to store function parameter values, local variables, etc
  • 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 program

The meaning of four memory areas: the data stored in different areas give us different life cycles and give us greater flexibility in programming

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
    The code area is read-only because it prevents the program from accidentally modifying its instructions
  • Global area:
    Global and static variables. Constants are stored here
    The constant area contains string constants and const decorated global constants
    The data in this area is released by the operating system at the end of the program
    eg:
//global variable
int g_a = 10;
int g_b = 10;

//Global constant
const int c_g_a = 10;
const int c_g_b = 10;

int main() {

	//local variable
	int a = 10;
	int b = 10;

	//Print address
	cout << "local variable a The address is: " << (int)&a << endl;
	cout << "local variable b The address is: " << (int)&b << endl;

	cout << "global variable g_a The address is: " <<  (int)&g_a << endl;
	cout << "global variable g_b The address is: " <<  (int)&g_b << endl;

	//Static variable
	static int s_a = 10;
	static int s_b = 10;

	cout << "Static variable s_a The address is: " << (int)&s_a << endl;
	cout << "Static variable s_b The address is: " << (int)&s_b << endl;

	cout << "The string constant address is: " << (int)&"hello world" << endl;
	cout << "The string constant address is: " << (int)&"hello world1" << endl;

	cout << "Global constant c_g_a The address is: " << (int)&c_g_a << endl;
	cout << "Global constant c_g_b The address is: " << (int)&c_g_b << endl;

	const int c_l_a = 10;
	const int c_l_b = 10;
	cout << "Local constant c_l_a The address is: " << (int)&c_l_a << endl;
	cout << "Local constant c_l_b The address is: " << (int)&c_l_b << endl;

	system("pause");

	return 0;
}

1.2 after program operation

  • Stack area:
    It is automatically allocated and released by the compiler to store the parameter values and local variables of the function
    [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 a = 10;
	return &a;
}

int main() {

	int *p = func();

	cout << *p << endl;//a=10 will be output for the first time, because the compiler will automatically store the value of the local variable once
	cout << *p << endl;//The second output is garbled, because the compiler automatically releases the value of the local variable

	system("pause");

	return 0;
}

  • Stacking 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 program
    In C + +, the new keyword is mainly used to open up memory in the heap
int* func()
{
	int* a = new int(10);
	return a;
}

int main() {

	int *p = func();

	cout << *p << endl;
	cout << *p << endl;//Constant output p=10
    
	system("pause");

	return 0;
}

1.3 new operator

Using new operator in C + + to open up data in heap
The data developed in the heap area is manually developed by the programmer, manually released, and released by using the operator delete

Syntax: new data type

For the data created with new, the pointer of the type corresponding to the data will be returned

//Basic grammar
int* func()
{
    // Create integer data in heap
    // new returns a pointer to the data type
	int* a = new int(10);
	return a;
}

int main() {

	int *p = func();

	cout << *p << endl;
	cout << *p << endl;

	//Using delete to release heap data
	delete p;

	//cout << *p << endl; // An error is reported. The free space is inaccessible

	system("pause");

	return 0;
}

//Heap array
int main() {

	int* arr = new int[10];

	for (int i = 0; i < 10; i++)
	{
		arr[i] = i + 100;
	}

	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << endl;
	}
	//Release array delete followed by []
	delete[] arr;

	system("pause");

	return 0;
}


2 references

2.1 nature and basic grammar of reference

Essence: the essence of reference is implemented internally in c + +, which is a pointer constant
Function: alias variables,
Syntax: data type & alias = original name

int main() {

	int a = 10;
	int &b = a;//Operation on b is equivalent to operation on variable a

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
    // 10
    // 10

	b = 100;

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
    // 100
    // 100

	system("pause");

	return 0;
}

[note]:

  • &(Reference) = = > used to transfer values. When it appears on the left of a variable in a variable declaration statement, it indicates that the declaration is a reference
  • &(take address operator) = = > used to get the first address. It appears to the right of the equal sign when assigning an initial value to a variable or as a unary operator in an execution statement, indicating the address of the take object
//Nature of reference
//Found to be a reference, converted to int * const ref = & A;
void func(int& ref){
	ref = 100; // Ref is a reference, converted to * ref = 100
}
int main(){
	int a = 10;
    
    //Automatically convert to int * const ref = & A; Pointer constants are pointer points that cannot be changed, which also explains why references cannot be changed
	int& ref = a; 
	ref = 20; //It is found internally that ref is a reference, which is automatically converted to: * ref = 20;
    
	cout << "a:" << a << endl;
	cout << "ref:" << ref << endl;
    
	func(a);
	return 0;
}

2.2 reference precautions

  • Reference must be initialized
  • The reference cannot be changed after initialization
int main() {

	int a = 10;
	int b = 20;
	//int &c; // Error, reference must be initialized
	int &c = a; //Once initialized, it cannot be changed
	c = b; //This is an assignment operation, not a change reference

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
	// 20
    // 20
    // 20
	system("pause");

	return 0;
}

2.3 reference function parameters

Function: when passing a function parameter, you can use the reference technology to make the formal parameter modify the argument
Advantages: pointer modification arguments can be simplified

//1. Value transfer
void mySwap01(int a, int b) {
	int temp = a;
	a = b;
	b = temp;
}

//2. Address transfer
void mySwap02(int* a, int* b) {
	int temp = *a;
	*a = *b;
	*b = temp;
}
//Parameter: pass in the address and receive it with a pointer

//3. Reference transfer
void mySwap03(int& a, int& b) {
	int temp = a;
	a = b;
	b = temp;
}
//Parameter: alias. A below is the alias of a above. It can be modified by alias operation. The modification by original name operation is the same
int main() {

	int a = 10;
	int b = 20;
    // Value passing, formal parameters do not modify arguments
	mySwap01(a, b);
	cout << "a:" << a << " b:" << b << endl;
    // a:10 b:20

    // Address passing, formal parameters modify arguments
	mySwap02(&a, &b);
	cout << "a:" << a << " b:" << b << endl;
    // a:20 b:10

    // When passed by reference, the formal parameter modifies the argument
	mySwap03(a, b);
	cout << "a:" << a << " b:" << b << endl;
    // a:10 b:20

	system("pause");

	return 0;
}

2.4 reference function return value

Function: a reference can exist as the return value of a function
Note: do not return local variable references
Usage: function call as lvalue

//Returns a local variable reference
//The data type is followed by &, which is equivalent to returning by reference 
int& test01() {                                   
	int a = 10; //Local variables are stored in the stack area
	return a;
}

//Returns a static variable reference
int& test02() {
    // Static variables are stored in the global area, and the data on the global area is released by the system after the program is completed
	static int a = 20;
	return a;
}

int main() {

	//Cannot return a reference to a local variable
    //Because local variables will be released automatically after operation
	int& ref = test01();
	cout << "ref = " << ref << endl;
	cout << "ref = " << ref << endl;
    // The result is correct for the first time because the compiler has made reservations
    // The second result is wrong because a's memory has been released

	//If the function is an lvalue, it must return a reference
	int& ref2 = test02();
	cout << "ref2 = " << ref2 << endl;
	cout << "ref2 = " << ref2 << endl;
    // 20
    // 20

	test02() = 1000;
    //The function call exists to the left of the equal sign: the function call is the left value

	cout << "ref2 = " << ref2 << endl;
	cout << "ref2 = " << ref2 << endl;
    // 1000
    // 1000

	system("pause");

	return 0;
}

2.5 constant reference

Function: constant reference is mainly used to modify formal parameters to prevent misoperation

In the function parameter list, const can be added to modify the parameter to prevent the parameter from changing the argument

//The scene used by reference is usually used to modify formal parameters
void showValue(const int& v) {  
    //If const is added, the formal parameters cannot be modified
	//v += 10;
	cout << v << endl;
}

int main() {

	//int& ref = 10;   The reference itself requires a legal memory space, so this line of error
	//Just add const. The compiler optimizes the code. Int temp = 10; const int& ref = temp;
	const int& ref = 10;

	//ref = 100;  // Variables cannot be modified after const is added
	cout << ref << endl;

	//Using constant reference in function to prevent misoperation and modify arguments
	int a = 10;
	showValue(a);
	system("pause");
	return 0;
}

2.6 value transfer, pointer transfer and reference transfer

Tags: C++

Posted on Fri, 08 Oct 2021 15:19:41 -0400 by dcampbell18