Talking about C++ | References

Table of contents

introduce

1. Basic use of references

(1) Referenced concepts:

(2) Representation method of reference

(3) Precautions for reference

(4) Reference authority

2. The nature of citations

3. References and functions

 (1) Reference as a function parameter

 (2) Reference as function return value

4. Constant reference

5. References and pointers


introduce

A nickname, also known as a nickname, is a name given to a person by others based on his characteristics in addition to his real name, and most of them contain intimacy, hatred or joking meanings. Then in C++, in order to alias an existing variable, a reference is generated. A reference is an alias to an existing variable.

 1. Basic use of references

(1) Referenced concepts:

A reference is not a new definition of a variable, but an alias for an existing variable . The compiler will not open up a new memory space for the reference variable , and it shares a memory space with the variable it refers to .

(2) Representation method of reference

type  & alias  = original name ;

Xiaobai: Isn't & a bitwise AND?

Xiao Ming: This is actually operator overloading . Through overloading, the same operator will have different meanings. The compiler uses the context to determine the meaning of an operator.

Xiaobai: Ah, that’s how it is. I said & why it still takes the address character, I understand.

code example

#include <iostream>
using namespace std;
int main() {
	int money = 99999;
	int& money_1 = money;
	cout << "money=" << money<<endl;
	cout << "money_1=" << money_1<<endl;
	return 0;
}

Xiaobai: Sure enough, their values ​​are equal, so how to determine that they share a memory space?

Xiao Ming: Let's debug it together.

 Xiao Ming: Look, the reference and the object it refers to are the same address.

Xiao Bai: Got it, Xiao Ming is amazing.

(3) Precautions for reference

1. References  must be initialized at definition time

2. A variable can have multiple references, but a reference can only refer to one variable .

3. Once the reference is initialized, it cannot be changed .

1. The reference must be initialized when it is defined

Since a reference is an alias to an existing variable, the variable must be specified (initialized) when using a reference.

int& a;//错误,未初始化

 2. A variable can have multiple references, but a reference can only refer to one variable

In C++ syntax, a variable has multiple references, just like a person can have multiple nicknames. But a reference variable can only point to one reference object.

Code example:

#include <iostream>
using namespace std;
int main() {
	int x = 100;
	int& y = x;
	int& z = x; 
	return 0;
}

3. Once the reference is initialized, it cannot be changed . 

Once a reference points to a referenced object, the referenced object cannot be changed.


Xiaobai: Ahhh, so much content, my head can’t remember it!

Xiao Ming: Take your time, what don't you understand?

Xiaobai: Why can a reference only refer to one object?

Xiao Ming: You think, if a reference type is an alias of two objects at the same time, how does the computer know which one to use when compiling?

Xiaobai: That is to say, when pointing to multiple objects at the same time, is it ambiguous ?

Xiao Ming: Right.

Xiaobai: Then why can't the reference object be changed after initialization?

Xiao Ming: This involves the essence of citation, which will be discussed later in the article.

Xiaobai: OK, I will continue to work hard.

(4) Reference authority

Citation principle: The authority of the reference to the original variable cannot be enlarged.

 Code example:

#include <iostream>
using namespace std;
int main() {
	int x = 100;
	int& y = x;
	//权限不变可行
	const int& z = x; 
	//权利缩小可行
	return 0;
}

No expansion of authority is feasible

Code example:

#include <iostream>
using namespace std;
int main() {
	const int x = 100;
	int& y = x;
	//权限扩大可行
	const int& z = x; 
	//权利不变可行

	return 0;
}

Existence expansion is not feasible.

Xiaobai: I know this. Just like the squad leader directs the army commander to work, the army commander just kicks when he goes up.

Xiao Ming: Hahahaha, yes, the authority cannot be expanded , it can only be reduced


2. The nature of citations

The essence of reference is a pointer constant implemented inside C++

Code example: 

#include <iostream>
using namespace std;
int main() {
	int a = 10;
	int& b = a;
	//本质:int* const b=&a
	b = 100;
	//本质:*b=100;
	return 0;
}

Xiaobai: That’s how it is. This explains why the reference object cannot be changed after initialization.

Xiao Ming: Yes, because const modifies b, the value stored in b cannot be changed, so the memory address pointed to by b cannot be changed, so the reference object cannot be changed after the reference is initialized.

Xiaobai: The essence of this quote is still a bit confusing...

Xiao Ming: You can understand it this way. When the code is compiled to int& b=a , the compiler actually executes int * const b=&a . When b=100 is executed , the editor actually executes *b=100 .

Xiaobai: I can understand that the two ways of writing are the same, but is the reference simplified?

Xiao Ming: Yes.

3. References and functions

(1) Reference as a function parameter

Function: When a function passes parameters, you can use the reference technique to let the formal parameters modify the actual parameters

Advantages: It can simplify the pointer to modify the actual parameter, and it is also safer

It is generally believed that there are two forms of function parameter passing, value passing and address passing. A formal parameter passed by value is a temporary copy of the actual parameter . The address passing is to pass the pointer , and access the memory area where the actual parameter is located through the pointer. Therefore, address transfer does not need to open up new space, so it is faster and can reduce memory.

Value passing code example:

#include <iostream>
using namespace std;
void swap(int x, int y) {
	int temp = x;
	x = y;
	y = temp;
	cout << "形参:" << "x=" << x << ' ' << "y=" << y << endl;
}
int main() {
	int x = 10, y = 20;
	swap(x,y);
	cout << "实参:" << "x=" << x <<' ' << "y=" << y << endl;
	return 0;
}

 Passing by value does not change the value of the actual parameter

 Address transfer code example:

#include <iostream>
using namespace std;
void swap(int* x, int* y) {
	int temp = *x;
	*x = *y;
	*y = temp;
	cout << "形参:" << "x=" << x << ' ' << "y=" << y << endl;
}

int main() {
	int x = 10, y = 20;
	swap(&x,&y);
	cout << "实参:" << "x=" << x <<' ' << "y=" << y << endl;
	return 0;
}

 Address passing can change the value of the actual parameter

 Xiaobai: I almost understand it, but what does it mean that the formal parameter passed by value is a temporary copy of the actual parameter?

Xiao Ming: I will draw a picture and you will know

 Xiaobai: Understood, passing by value is to open up a new space, but the content is the same

Xiao Ming: Right.

Xiaobai: What about address delivery?

Xiao Ming: Address passing is the use of pointers. Formal parameters are pointers to store actual parameters. Dereferencing will find the actual parameters.

Xiaobai: Got it, what about the reference as a formal parameter?

Xiao Ming: Have you forgotten the essence of quoting you just learned?

Xiaobai: Oh, I see, let me do this code, hehe.

#include <iostream>
using namespace std;
void swap(int& x, int& y) {
	int temp = x;
	x = y;
	y = temp;
	cout << "形参:" << "x=" << x << ' ' << "y=" << y << endl;
}

int main() {
	int x = 10, y = 20;
	swap(x,y);
	cout << "实参:" << "x=" << x <<' ' << "y=" << y << endl;
	return 0;
}

Xiao Ming: That's right, that's how the reference is written as a formal parameter.

Xiao Ming: Can you write a pointer version based on the essence of the reference?

Xiaobai: It's a small problem, let me show my skills.

 Xiaobai: How about it, am I right?

Xiao Ming: Yes, in fact, the reference is also passed by address , but because of the const, the pointed object cannot be changed.

Xiaobai: I see.

Xiao Ming: Compared with pointers, references are simpler , and because of const, they are safer than pointers .

(2) Reference as function return value

Quoting as a function return value feature:

1. A reference to a local variable cannot be returned .

2. Function calls can be used as lvalues .

 Xiaobai: Why can't the reference return the reference of the local variable?

Xiao Ming: A reference is essentially a pointer, a pointer constant. Because a pointer cannot return the address of a local variable.

Xiaobai: Can't a pointer return a pointer to a local variable?

Xiao Ming: Yes, because the local variable will be destroyed after the function is executed, and the memory of the variable will be returned to the system. At this time, the function returns the address of the variable, and if it is called, it is an illegal access and an invalid pointer.

Xiaobai: Oh, I understand, that is, after the function is executed, the address does not belong to the program, and accessing it again is illegal.

Xiao Ming: Right.

Code example:

#include <iostream>
using namespace std;
int& test() {
	int n = 0;
	n = 100;
	return n;
}
int main() {
	int& res = test();
	cout << res << endl;
	cout << "系统清除" << endl;;
	cout << res<<endl;
	return 0;
}

Notice:

If the function returns out of the scope of the function, if the returned object has not been returned to the system, it can be returned by reference, and if  it has been system, it must be returned by value.

Xiaobai: Then only global variables can be created and global variables returned?

Xiao Ming: In fact, the static keyword is used. The static keyword is created in the global area (static area), and the life cycle is the entire program.

Xiaobai: Variables created by static, the program does not stop, and the variables are not destroyed, right?

Xiao Ming: Right.

Xiaobai: Still a little confused.

Xiao Ming: Don’t worry, let’s take a look at the code to understand.

Code example:

#include <iostream>
using namespace std;
int& test() {
	static int n = 0;
	n = 100;
	return n;
}
int main() {
	int& res = test();
	cout << res << endl;
	cout << "系统清除" << endl;
	cout << res<<endl;
	return 0;
}

Xiaobai: Understood, as long as the return value is not destroyed in the function call, is it okay?

Xiao Ming: Right.

Xiaobai: What does it mean that the function call can be used as an lvalue?

Xiao Ming: That is to say, the function can be placed on the left side of the equal sign to assign a value to the function .

Xiaobai: Assigning a value to a function is impossible, right?

Xiao Ming: In fact, when the return value of a function is a reference, a reference variable will be generated, but it has no name. Assigning a value to a function is actually assigning a value to the reference.

Xiaobai: I still don’t understand.

Xiao Ming: Let's look at the code.

Code example:

#include <iostream>
using namespace std;
int& test() {
	static int n = 0;
	n = 100;
	return n;
}
int main() {
	int& res = test();
	test() = 99;
	cout << res<<endl;
	return 0;
}

Xiaobai: Oh, that is to say, the function is equivalent to an anonymous reference at this time, and the function as an lvalue is equivalent to modifying the value of n through an anonymous reference.

Xiao Ming: Yes, then you can see what the code below means.

Code example:

#include <iostream>
using namespace std;
int& test() {
	static int n = 0;
	n = 100;
	return n;
}
int main() {
	int res = test();
	test() = 99;
	cout << res<<endl;
	return 0;
}

 Xiaobai: Can the int type receive values ​​of the int& type?

Xiao Ming: Yes, it is actually equivalent to dereferencing the anonymous reference and passing the value to res.

Xiaobai: I still don’t understand.

Xiao Ming: Let's continue to look at the code.

Code example:

#include <iostream>
using namespace std;
int& test() {
	static int n = 0;
	n = 100;
	return n;
}
int main() {
	/*int res = test();*/
	int& m = test();
	int res = m;
	test() = 99;
	cout << res<<endl;
	return 0;
}

 Xiao Ming: Understand that.

Xiaobai: I understand.

Xiao Ming: So I don’t understand if it’s changed to anonymous references?

Xiaobai: Understood, that is, directly through, anonymous references to pass values ​​to variables .

Xiao Ming: Right.

4. Constant reference

const type  & alias  = original name ;

1. It can directly point to a constant.

2. In the formal parameter list of the function, it is possible to prevent the actual parameters from being changed by changing the formal parameters.

Xiaobai: I understand this is equivalent to a pointer constant pointing to a constant.

Xiao Ming: Yes, for example, const int* const p; the value of p cannot be changed, and the value of *p cannot be changed either.

Xiaobai: It can directly point to a constant, what does it mean?

Xiao Ming: In fact, the constants are stored in the constant area, the declaration cycle and the program coexist, and the constant area has only read-only permissions, no write permissions. If you use ordinary references, because the references can be changed to point to the value of the memory, it belongs to the expansion of permissions, and an error will be reported. If you use constant references, the references only have read permissions, and you can point to the constant area.

Xiaobai: I'm a little confused.

Xiao Ming: It’s okay, let’s take a look at the code.

Code example:

#include <iostream>
using namespace std;
int main() {
	/*int& res = 10;*/
	const int& res = 10;
	cout << 10;
	return 0;
}

 Xiaobai: Understood, to prevent actual parameters from changing, and thus to change actual parameters, is to prevent accidental changes of formal parameters.

Xiao Ming: Great, until the quick answer, we only need the value in some scenarios, but we are not allowed to change the value of the reference, you can use a constant reference to prevent careless change of the value of the formal parameter.

Code example :

#include <iostream>
using namespace std;
void text(const int& x) {
	//x = 100;
	cout << x;
}
int main() {
	/*int& res = 10;*/
	text(9);
	return 0;
}

 5. References and pointers

A reference is actually a pointer. The essence of a reference is a pointer constant implemented inside C++ . When building a reference to int& b=a , the compiler actually executes int * const b=&a . When b=100 , the editor actually executes * b=100 . The b encountered later can be regarded as the *p of the pointer constant, but it also depends on the context. In fact, the reference also takes up space , but it is hidden by C++. 

Macro differences:
1. The value of the pointer can be empty, but the value of the reference cannot be NULL , and the reference must be initialized when it is defined ;.
2. After the reference refers to an entity during initialization, it cannot refer to other entities (pointer constants), and the pointer can be at any time. Point to any entity of the same type.
3. The meaning is different in sizeof: the reference result is the size of the reference type (sizeof(*p)), but the pointer is always the number of bytes occupied by the address space (4/8).
4. The reference increment means that the referenced entity is increased by 1 ((*p)++), and the pointer auto-increment means that the pointer is offset backward by the size of the byte.
5. There are multi-level pointers, but no multi-level references.
6. There are different ways to access entities. The pointer needs to be explicitly dereferenced, and the reference compiler will handle it by itself.
 

Understand the nature of citations, these will actually be much easier to understand.

(The rest of the C++ series are being updated continuously, please pay attention three times, this article is over)

Guess you like

Origin blog.csdn.net/m0_73731708/article/details/131334390