[C + + basic] usage and constant reference

Posted by daveh33 on Tue, 22 Feb 2022 03:28:04 +0100

1.1 basic use of references

  • Function: alias the variable. The new alias points to the same block of memory.
  • Syntax: data type & alias = original name
#include<iostream>
using namespace std;

//Reference, alias variables
int main(){
	int a = 10;
	int &b = a;
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	//a = 10
	//b = 10

	b = 100;
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	//a = 100
	//b = 100
	system("pause");
	return 0;
}

1.2 notes for reference

  • The reference must be initialized (the alias of which variable must be specified)
  • The reference cannot be changed after initialization. For example, it is not allowed to change b into the alias of c (as follows:
#include<iostream>
using namespace std;

//Reference, alias variables
int main(){
	int a = 10;
	//1. Reference must be initialized
	//int &b;// error
	int &b = a;

	//2. The reference cannot be changed after initialization
	int c = 20;

	//To make b an alias of c, this is an assignment operation, not a reference change
	b = c;//Here is the memory pointed to by b, with a value of 20

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

1.3 reference as function parameter

Function parameter passing is divided into value passing (formal parameters cannot modify arguments) and address passing.

  • Function of reference as a function parameter: when a function passes a parameter, you can use reference to let the formal parameter modify the argument. At this time, you don't need to use address transfer.
  • Advantages: pointer modification arguments can be simplified.
#include<iostream>
using namespace std;

//Exchange function
//1. Value transfer
//2. Address transmission
//3. Reference transfer

void mySwap01(int a, int b){
	int temp = a;
	a = b; 
	b = temp;

	cout << "swap01 a = " << a << endl;
	cout << "swap01 b = " << b << endl;  
	cout << endl;
}

//2. Address transfer, receiving address with pointer
void mySwap02(int* a, int* b){
	int temp = *a;
	*a = *b; 
	*b = temp;

	cout << "swap02 a = " << a << endl;
	cout << "swap02 b = " << b << endl;  
	cout << endl;
}

//Reference passing, where the a of the formal parameter is the alias of the argument a (only with the same name)
void mySwap03(int &a, int &b){
	int temp = a;
	a = b; 
	b = temp;

	cout << "swap03 a = " << a << endl;
	cout << "swap03 b = " << b << endl;  
	cout << endl;
}

int main(){
	int a = 10, b = 20;
	//1. Value passing, formal parameters will not modify arguments
	//mySwap01(a, b);
	//2. Address passing, address passing, formal parameters will modify arguments
	//mySwap02(&a, &b);
	//3. Reference passing, formal parameters will also modify arguments
	mySwap03(a, b);

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	system("pause");
	return 0;
}
  • Summary:
    • Reference passing, where the a of the formal parameter is the alias of the argument a (only with the same name)
    • The effect of referencing parameters is the same as that of address passing, but the syntax of reference is clearer.

1.4 reference as 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.

(1) Do not return local variable references. Chestnuts are as follows. The second result is wrong because a's memory has been released, and the first time is correct because the compiler has reserved it.

#include<iostream>
using namespace std;

//1. Do not return a reference to a local variable
int& test01(){
	//Local variables are stored in the stack area in four areas
	int a = 10;
	return a;
}

int main(){
	int &ref = test01();
	//For the first time, the compiler made a reservation
	cout << "ref = " << ref << endl;
	//The second result is wrong because the memory of a has been released
	cout << "ref = " << ref << endl;
	system("pause");
	return 0;	
}


(2) Function call as lvalue.
Now do not return the reference of the local variable. After using static, let the function return the reference of the static variable.
The original name is assigned 1000, and the alias access is also 1000. If the return value of a function is a reference, the call of this function can be used as an lvalue.

#include<iostream>
using namespace std;

//1. Do not return a reference to a local variable
int& test01(){
	//Local variables are stored in the stack area in four areas
	int a = 10;
	return a;
}

//2. Function calls can be used as lvalues
int& test02(){
	static int a = 10; //Static variables, stored in the global area
	//The data on the global area is released by the system after the program ends
	return a;
} 

int main(){
	//int &ref = test01();
	//For the first time, the compiler made a reservation
	//cout << "ref = " << ref << endl;
	//The second result is wrong because the memory of a has been released
	//cout << "ref = " << ref << endl;

	int &ref2 = test02();
	cout << "ref2 = " << ref2 << endl;
	cout << "ref2 = " << ref2 << endl;

	test02() = 1000;//In fact, it is equivalent to making an assignment of a=1000, and ref2 is the alias of A 
	cout << "ref2 = " << ref2 << endl;
	cout << "ref2 = " << ref2 << endl;
	system("pause");
	return 0;	
}

1.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.

For example, const below limits that ref is read-only and cannot be modified. If ref = 20, an error will be reported. The expression must be a modifiable lvalue.

#include<iostream>
using namespace std;

int main(){
	
	//const reference 
	//Usage scenario: used to modify formal parameters to prevent misoperation
	int a = 10;
	//int &ref = 10; // The reference must refer to a legal memory space
	
	//Add const, and the compiler modifies the code to int temp = 10; const int &ref = temp;
	const int &ref = 10; //The reference must refer to a legal memory space
	
	//The expression must be a modifiable lvalue
	//ref = 20;
	
	system("pause");
	return 0;
}

(2) Usage scenario: used to modify formal parameters to prevent misoperation.
For example, in the following scenario, we only want the showValue function to print the val variable, but because the formal parameter uses a reference, the value of the passed in a variable has also changed. If there are many lines of code, it is easy to forget that the A has changed (the original intention is not to change a), so we can add const to the formal parameter, and an error prompt will be reported (safer):


Therefore, when a function uses a reference, the argument will be changed after the formal parameter is modified. If const is added, an error prompt will be reported to prevent misoperation of the formal parameter (for example, the external argument will be changed after modifying the formal parameter value):

#include<iostream>
using namespace std;

//Print data function
void showValue(const int &val){
	//val = 1000;
	cout << "val = " << val << endl;
}

int main(){
	
	//const reference 
	//Usage scenario: used to modify formal parameters to prevent misoperation
	int a = 100;
	showValue(a);
	system("pause");
	return 0;	
}

Topics: C++ Back-end