[C++] C++ reference detailed explanation ① (The essence of variables - introduce the concept of "reference" | Introduction to reference syntax | References as function parameters | Complex type references as function parameters)





1. The essence of variables - introducing the concept of "reference"



The "reference" syntax is unique to the C++ language, and there is no reference to this concept in the C language;


1. The essence of variables - memory aliases


Before analyzing the references, let's review the variables:

In [C Language] Variable Essence (Variable Concept | Variable Essence - Memory Space Alias ​​| Variable Storage Location - Code Area | Variable Three Elements) blog, the essence of variables is introduced:

The essence of the variable is the "alias" of the memory space, referred to as "memory alias", which is equivalent to "house number";

Programs in C language/C++ language apply for memory space through variables, and name the memory space, and the name is the variable name;

In the following code, defining the variable a means applying for 4 bytes of memory in the stack memory. The alias of the 4 bytes of continuous memory is a. Assigning a value of 10 to the variable means storing 10 in the 4 bytes of memory;

int a = 10;

Through the "variable name", you can use the continuous memory space represented by the variable name, and then use the variable a to calculate, that is, use the data in the 4-byte memory represented by the variable a to calculate;


2. Introduce the concept of "reference" - the memory alias of the defined variable


As discussed below, the above variable a is an alias of a 4-byte continuous memory space, so can this 4-byte memory space only have one memory alias? Or can it have multiple memory aliases?

The answer is yes, if you want to assign a "memory alias" to the above 4-byte memory space again, you need to use "reference";


"Reference" is the memory alias of the defined variable;

  • The first time an alias is assigned to a piece of memory is when defining a variable;
  • Assigning an alias to the memory for the second time is to obtain the "reference" of the variable;

3. The advantages of "reference"


References in the C++ language are special variables through which existing variables can be accessed;


Advantages of using "references":

  • Improve access efficiency: When passing parameters to a function, using references can reduce consumption, similar to passing in pointers. If you pass in a large array, you need to copy the entire array as a variable copy, and copying will consume a lot of performance;
  • Improve code readability: When using references, it is similar to a first-level pointer. During the use of references, there is no need to use the address symbol & and pointer symbols *, which improves code readability and maintainability;
  • Function return value: function reference parameters can be used as return values;




2. Introduction to citation syntax




1. Grammatical description


The "quote" syntax is as follows:

类型& 引用名称 = 变量;

The & symbol is recommended to be written next to the type, separated from the reference name by a space ;

(The pointer symbol * is also recommended to be close to the pointer type, separated from the pointer name with spaces, such as: int* p = NULL;)

After the reference is defined, it can be used as a variable;

Through reference, variables can be manipulated, accessed, and references modified, and variables will be modified accordingly;


When using references as function parameters,

  • The actual parameter passed in does not need to be obtained by using the address symbol, and the variable can be directly passed into the function;
  • When accessing a reference in a function, you do not need to use a pointer, and directly use the reference to access the variable passed in;

Code example:

	// 定义变量 a , 变量本质是内存别名
	int a = 10;

	// 定义引用 b , 是变量 a 的别名
	int& b = a;

	// 通过引用修改变量的值
	b = 100;

Reference is a concept of C++, reference cannot be used in C language;

The implementation of the above code in C language is completely different, the following is the implementation of the above code in C language:

	// 定义变量 a , 变量本质是内存别名
	int a = 10;

	// 获取 变量 a 的地址 , 赋值给 指针常量 b 
	// 指针常量 是 常量 - 指针本身不能修改 , 常量指针 是 指针 - 指向常量的指针 
	// 左数右指 , const 在 指针 * 的右边 , 指针 是常量 , 指针的指向不能更改
	int* const b = &a;

	// 通过 指针常量 修改 指针指向的内存空间的值
	// 指针指向不能修改 , 指向的内存中的内容可以修改
	*b = 100;

In the above code,

  • First, get the address of the variable a and assign it to the pointer constant b;
    • Pointer constants are constant - the pointer itself cannot be modified;
    • A constant pointer is a pointer - a pointer to a constant;
    • Left counts right, const is on the right of the pointer *, the pointer is a constant, and the pointing of the pointer cannot be changed;
  • Then, modify the value of the memory space pointed to by the pointer through the pointer constant;
    • The address pointed to by the pointer cannot be modified;
    • The contents of the memory pointed to by the pointer can be modified;

2. Code example - definition and use of references


In the following code, reference b is an alias of variable a, and the memory space of variable a can be accessed through reference b;

In the code, the reference b and the variable a are printed at the same time, and the variable value 10 can be printed;

Modify the value of reference b, the value of variable a will also be modified;


Code example:

// 包含 C++ 头文件
#include "iostream"

// 使用 std 标准命名空间
//		该命名空间中 , 定义了很多标准定义
using namespace std;

// 导入 C 头文件
#include <stdio.h>

int main()
{
    
    
	// 定义变量 a , 变量本质是内存别名
	int a = 10;

	// 定义引用 b , 是变量 a 的别名
	int& b = a;

	// 打印 变量 a 和 引用 b 的值
	printf("a = %d, b = %d\n", a, b);

	// 通过引用修改变量值
	b = 100;

	// 打印 变量 a 和 引用 b 的值
	printf("a = %d, b = %d\n", a, b);


	// 控制台暂停 , 按任意键继续向后执行
	//system("pause");
    return 0;
}

Results of the :

a = 10, b = 10
a = 100, b = 100

insert image description here





3. References as function parameters




1. Ordinary references must be initialized - except for function parameters


Ordinary references must be attached to a variable, and must be initialized when defining a "reference", otherwise the following error will be reported:

引用 变量 x 需要初始值设定项

insert image description here


There is a special case here, which can be declared without initialization,

When "reference" is used as a function parameter, it does not need to be initialized;


Using a reference as a function parameter has the same effect as a first-level pointer, and it is relatively simple to use without operating pointers;

The reference is more in line with the Java / C# language style, and does not need to operate cumbersome pointers;


Define two variables:

	// 定义变量 a , b ,  变量本质是内存别名
	int a = 10, b = 20;

Write a function that swaps the values ​​of these two variables;


2. Code example - use ordinary variables as parameters (variable exchange cannot be realized)


In the following code, the exchange function defined, the formal parameters passed in are ordinary variables;

The parameter is an ordinary variable, and the actual parameter is a copy of the variable. The scope of the variable is limited to the function, and cannot be passed outside the function, and the external variable cannot be changed;


Code example:

// 包含 C++ 头文件
#include "iostream"

// 使用 std 标准命名空间
//		该命名空间中 , 定义了很多标准定义
using namespace std;

// 导入 C 头文件
#include <stdio.h>

// 交换 a 和 b 的值
// 该函数无法实现交换 , 因为传入的实参只是副本
// 并不能真实的改变传入的值
void swap(int a, int b) 
{
    
    
	int c = 0;
	c = a;
	a = b;
	b = c;
}

int main()
{
    
    
	// 定义变量 a , b ,  变量本质是内存别名
	int a = 10, b = 20;

	// 打印 变量 a 和 引用 b 的值
	printf("a = %d, b = %d\n", a, b);

	// 传入变量副本 : 交换 a 和 b 的值 , 交换失败
	swap(a, b);
	// 打印 变量 a 和 引用 b 的值
	printf("a = %d, b = %d\n", a, b);


	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
    return 0;
}

Results of the :

a = 10, b = 20
a = 10, b = 20

insert image description here


3. Code example - using pointer variables as parameters (the method of realizing variable exchange in C language)


In the following code, the variable exchange function is implemented in C language;

The function parameter receives a pointer variable as a parameter, and the actual parameter passed in is the address of the variable;

Inside a function, access to a variable needs to be done via the pointer * notation ;

In this way, the value exchange of external variables can be realized, but the code is very complicated and cumbersome to operate with the pointer *, and it is not easy to understand;


Code example:

// 包含 C++ 头文件
#include "iostream"

// 使用 std 标准命名空间
//		该命名空间中 , 定义了很多标准定义
using namespace std;

// 导入 C 头文件
#include <stdio.h>

// 交换 a 和 b 的值
// C 语言中可以使用该方法
void swap(int* a, int* b)
{
    
    
	int c = 0;
	c = *a;
	*a = *b;
	*b = c;
}

int main()
{
    
    
	// 定义变量 a , b ,  变量本质是内存别名
	int a = 10, b = 20;

	// 打印 变量 a 和 引用 b 的值
	printf("a = %d, b = %d\n", a, b);

	// 传入指针地址 : 交换 a 和 b 的值 , 交换成功
	swap(&a, &b);
	// 打印 变量 a 和 引用 b 的值
	printf("a = %d, b = %d\n", a, b);


	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
    return 0;
}

Results of the :

a = 10, b = 20
a = 20, b = 10

insert image description here


4. Code example - using references as parameters (the method of variable exchange in C++ language)


In the code below, variable swapping is also implemented using references as function parameters;

The use of references in C++ is very simple, without using pointers for operations;

When using a reference, you can see the effect of the reference, which is actually equivalent to a first-level pointer;

When using a reference as a function parameter, the actual parameter passed in does not need to be obtained by taking the address symbol, and the variable can be directly passed into the function. When obtaining the value of the reference in the function, there is no need to use a pointer, and the reference is directly used to access the passed in variable;


Code example:

// 包含 C++ 头文件
#include "iostream"

// 使用 std 标准命名空间
//		该命名空间中 , 定义了很多标准定义
using namespace std;

// 导入 C 头文件
#include <stdio.h>

// 交换 a 和 b 的值
// C++ 中推荐的方法
// 使用引用作为函数参数 
void swap(int& a, int& b)
{
    
    
	int c = 0;
	c = a;
	a = b;
	b = c;
}

int main()
{
    
    
	// 定义变量 a , b ,  变量本质是内存别名
	int a = 10, b = 20;

	// 打印 变量 a 和 引用 b 的值
	printf("a = %d, b = %d\n", a, b);

	// 传入引用本 : 交换 a 和 b 的值 , 交换成功
	swap(a, b);
	// 打印 变量 a 和 引用 b 的值
	printf("a = %d, b = %d\n", a, b);


	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
    return 0;
}

Results of the :

a = 10, b = 20
a = 20, b = 10

insert image description here


5. Code example - complete code example


Complete code example:

// 包含 C++ 头文件
#include "iostream"

// 使用 std 标准命名空间
//		该命名空间中 , 定义了很多标准定义
using namespace std;

// 导入 C 头文件
#include <stdio.h>

// 交换 a 和 b 的值
// 该函数无法实现交换 , 因为传入的实参只是副本
// 并不能真实的改变传入的值
void swap1(int a, int b) 
{
    
    
	int c = 0;
	c = a;
	a = b;
	b = c;
}

// 交换 a 和 b 的值
// C 语言中可以使用该方法
void swap2(int* a, int* b)
{
    
    
	int c = 0;
	c = *a;
	*a = *b;
	*b = c;
}

// 交换 a 和 b 的值
// C++ 中推荐的方法
void swap3(int& a, int& b)
{
    
    
	int c = 0;
	c = a;
	a = b;
	b = c;
}

int main()
{
    
    
	// 定义变量 a , b ,  变量本质是内存别名
	int a = 10, b = 20;

	// 打印 变量 a 和 引用 b 的值
	printf("a = %d, b = %d\n", a, b);

	// 传入变量副本 : 交换 a 和 b 的值 , 交换失败
	swap1(a, b);
	// 打印 变量 a 和 引用 b 的值
	printf("a = %d, b = %d\n", a, b);

	// 传入指针 : 交换 a 和 b 的值 , 交换成功
	swap2(&a, &b);
	// 打印 变量 a 和 引用 b 的值
	printf("a = %d, b = %d\n", a, b);

	// 传入引用 : 交换 a 和 b 的值 , 交换成功
	swap3(a, b);
	// 打印 变量 a 和 引用 b 的值
	printf("a = %d, b = %d\n", a, b);


	// 控制台暂停 , 按任意键继续向后执行
	//system("pause");
    return 0;
}

Results of the :

a = 10, b = 20
a = 10, b = 20
a = 20, b = 10
a = 10, b = 20

insert image description here





4. Complex type references as function parameters




1. Three transmission methods of complex type parameters


To define a structure type, there are three ways to pass the structure object to the function;

// 定义一个结构体 
// C++ 中结构体就是类
struct Student
{
    
    
	char name[64];
	int age;
};

First create the structure object in the stack memory, and assign a value to the object;

	Student s;
	s.age = 18;

I. Transfer the structure object itself


The first way, directly passing the structure object itself,

  • Function transfer: This method transfers a copy of the structure object, which needs to be copied and then passed to the function as an actual parameter. The copying process consumes a lot of performance;
  • Parameter access: The parameters passed in are normally accessed in the function, use. Access structure members;
  • Parameter modification: Modifying this parameter will not affect the value of the external structure object, because the modified copy is copied;
// 直接传入结构体类对象本身
void printStudent1(Student s)
{
    
    
	// 使用变量 , 直接使用 . 访问结构体成员
	cout << "printStudent1 开始执行 age : " << s.age << endl;
	s.age = 19;
}

II. Transfer structure pointer


The second way, pass the structure pointer,

  • Function transfer: This method transfers the structure pointer, which is actually a copy of the pointer, and hardly consumes performance;
  • Parameter access: The pointer parameter passed in is used in the function -> access to the structure member;
  • Parameter modification: Modify the parameter through the pointer, and the external structure object will also be modified;
// 传入结构体类对象指针
void printStudent2(Student* s)
{
    
    
	// 通过 问结构体指针 访问成员需要使用 -> 访问
	cout << "printStudent2 开始执行 age : " << s->age << endl;
	s->age = 20;
}

III. Passing structure references


The third way, pass structure reference,

  • Function transfer: This method transfers a structure reference, which is just an alias of a variable and hardly consumes performance;
  • Parameter access: The reference parameters passed in are used in the function. Access to structure members is the same as variable usage;
  • Parameter modification: Modify the parameter through the pointer, and the external structure object will also be modified;
// 传入结构体类对象指针
void printStudent2(Student* s)
{
    
    
	// 通过 问结构体指针 访问成员需要使用 -> 访问
	cout << "printStudent2 开始执行 age : " << s->age << endl;
	s->age = 20;
}

2. Code example - use three delivery methods to pass parameters


Code example:

// 包含 C++ 头文件
#include "iostream"

// 使用 std 标准命名空间
//		该命名空间中 , 定义了很多标准定义
using namespace std;

// 导入 C 头文件
#include <stdio.h>

// 定义一个结构体 
// C++ 中结构体就是类
struct Student
{
    
    
	char name[64];
	int age;
};

// 直接传入结构体类对象本身
void printStudent1(Student s)
{
    
    
	// 使用变量 , 直接使用 . 访问结构体成员
	cout << "printStudent1 开始执行 age : " << s.age << endl;
	s.age = 19;
}

// 传入结构体类对象指针
void printStudent2(Student* s)
{
    
    
	// 通过 问结构体指针 访问成员需要使用 -> 访问
	cout << "printStudent2 开始执行 age : " << s->age << endl;
	s->age = 20;
}

// 传入结构体类对象引用
void printStudent3(Student& s)
{
    
    
	// 使用 引用 跟普通变量用法相同, 不需要使用 -> 访问
	cout << "printStudent3 开始执行 age : " << s.age << endl;
	s.age = 21;
}

int main()
{
    
    
	Student s;
	s.age = 18;

	// 传入对象 消耗性能
	printStudent1(s);
	cout << "printStudent1 执行完毕 age : " << s.age << endl;

	// 传入指针 需要取地址
	printStudent2(&s);
	cout << "printStudent2 执行完毕 age : " << s.age << endl;

	// 传入引用 直接传入
	printStudent3(s);
	cout << "printStudent3 执行完毕 age : " << s.age << endl;


	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
    return 0;
}

Results of the :

printStudent1 开始执行 age : 18
printStudent1 执行完毕 age : 18
printStudent2 开始执行 age : 18
printStudent2 执行完毕 age : 20
printStudent3 开始执行 age : 20
printStudent3 执行完毕 age : 21
Press any key to continue . . .

insert image description here

Guess you like

Origin blog.csdn.net/han1202012/article/details/132416680