# [C + +] simple record of the reason for introducing the "reference" mechanism

Posted by maxat on Mon, 14 Feb 2022 20:34:43 +0100

📣🥳🥳🥳📣

✨ Hello! If this [article] is helpful to you 😄， I hope I can praise the blogger 👍 Encourage me 😘

📣🥳🥳🥳📣

# 🤔 Why introduce references?

In response to [why introduce references?] Before this problem, let's review the two call forms of functions: pass by value and pass by reference. In C language, address transmission can only be realized in the form of pointer.
Examples of value transfer methods are as follows 👇

```#include <iostream>
#include <vector>
using namespace std;

void swap(int x, int y);    // swap function declaration
void display(vector<int> vec);    // display function declaration

int main()
{
int num1 = 1, num2 = 2;
swap(num1, num2);    //You want to swap the values of num1 and num2
int num_arr = {num1, num2};
vector<int> num_vec(num_arr, num_arr+2);
display(num_vec);
return 0;
}

/* Function function: (imagine being able to) exchange the values of two objects of type int */
void swap(int x, int y) {
int temp = x;
x = y;
y = temp;
}

/* Function function: print each value in a vector template class object */
void display(vector<int> vec) {
for (int i = 1; i <= vec.size(); ++i) {
cout << "num" << i << " = " << vec[i-1] << endl;
}
}
```

The compilation results are as follows 👇

```num1 = 1
num2 = 2
```

It can be found that the expected results have not been achieved. This is because the value transfer method is only a simple copy when transferring parameters. When using the swap() function, the num1 and num2 objects passed in and the x and Y objects operated inside the swap() function actually have no other relationship except that the values are exactly the same. Therefore, no matter how to operate the x and y objects inside the function, it will not affect the num1 and num2 objects outside the swap() function. Therefore, we must implement it in the way of address transmission.
In addition, it should be noted that when we call the swap () function, a special area called the program stack will be established in memory. The program stack provides storage space for each function parameter, that is, the objects num1 and num2 are stored in the current special area. We call the objects located in this special area as local objects. Once the function body of swap() function is executed, this memory will be released (destroyed) immediately. Therefore, after the function is executed, the local objects x and y will also be destroyed.

For the address transmission mode, C + + not only can be implemented in the form of pointer, but also introduces the reference mechanism. Next, address transmission is realized in the form of pointer, and the code of the above example is changed as follows 👇

```#include <iostream>
#include <vector>
using namespace std;

void swap(int *x, int *y);    // With adjustment
void display(vector<int> vec);

int main()
{
int num1 = 1, num2 = 2;
swap(num1, num2);
int num_arr = {num1, num2};
vector<int> num_vec(num_arr, num_arr+2);
display(num_vec);
return 0;
}

void swap(int *x, int *y) {    // With adjustment
int temp = *x;    // There are adjustments. After the address is transmitted in the form of pointer, it is necessary to manually solve the address when using it. Later, it will be found that there is no need to manually solve the address when using the reference mechanism
*x = *y;    // There are adjustments.
*y = temp;    // With adjustment
}

/* Function function: print each value in a vector template class object */
void display(vector<int> vec) {
for (int i = 1; i <= vec.size(); ++i) {
cout << "num" << i << " = " << vec[i-1] << endl;
}
}
```

The compilation results are as follows 👇

```num1 = 2
num2 = 1
```

It is clear that the expected results have been achieved.

Next, use the reference mechanism to realize the address transmission mode. Just change the swap() function in the initial code as follows 👇

```void swap(int &x, int &y);
```

The compilation results are as follows 👇

```num1 = 2
num2 = 1
```

It can be found that the expected effect can also be achieved.

[back to the question, since the pointer can realize address transmission, why introduce the reference mechanism to realize address transmission?] The thinking results are as follows 👇

Compared with the pointer form, the reference mechanism does not need to manually use the de address operator, and it is very intuitive when calling the function. When modifying the function, the whole function body does not need to be adjusted at all. The introduction of the reference mechanism is specifically aimed at the needs of the address transmission scenario when the function is called. In this scenario, the reference mechanism can be used to replace the traditional pointer form, so as to avoid the troublesome problems of address resolution operation in the function body and function value transmission and address adjustment.

# 🤔 When to transmit value and address?

When defining a function, how to determine whether to pass a value or an address? The statement in Essential C + + is as follows 👇

One reason for addressing is that you want to be able to modify the incoming object directly. This reason is extremely important. (for example, the swap exchange function mentioned above cannot achieve the expected requirements if it does not adopt address transmission.)
Another reason for addressing is the desire to reduce the additional burden of copying large objects. However, this reason is less important and involves the efficiency of the procedure.

For the second reason, you can use the print function display() of the above example to illustrate. This function is defined as follows 👇

```void display(vector<int> vec) {
for (int i = 1; i <= vec.size(); ++i) {
cout << "num" << i << " = " << vec[i-1] << endl;
}
}
```

It can be found that the parameter transfer mode of the function is value transfer mode, which means that all elements in the vector will be copied every time the display operation is performed. If the address of the vector is directly passed in, that is, the address transmission method is adopted, for the vector with large capacity, the overhead can be reduced and the execution speed will be faster. Change as follows 👇

```void display(vector<int> &vec) {
for (int i = 1; i <= vec.size(); ++i) {
cout << "num" << i << " = " << vec[i-1] << endl;
}
}
```

# 🤔 What is the specific difference between a reference and a pointer?

A brief summary is as follows 👇

one ️⃣ A reference is a "restricted" pointer, which is safer. The reference definition must be initialized and only bound to the initial object as the alias of the object (while the pointer itself is an object. Using sizeof (Reference) gets the type size of the object it represents, while sizeof (pointer) gets the type size of the pointer object itself). Because it must be initialized and always bound to an object, there is no null reference, but the pointer can be changed at will (the pointer can also be understood as an ordinary variable, but its variable value is an address value, which is more special), Null pointers and wild pointers are allowed (wild pointers can be generated in a variety of scenarios. In one case, when multiple pointers point to a piece of memory and free drops one pointer, other pointers become wild pointers).

two ️⃣ About constant pointers, constant references, pointer constants, and reference constants
Constant pointer / constant reference means that it is impossible to reassign the variable pointed to / represented by this pointer / reference. Examples are as follows 👇

```int main() {
int x = 1;
const int *p = &x;    // const pointer
*p = 2;    // An error is reported. This operation is not possible
const int &x1 = x;    // const reference
x1 = 2;    //An error is reported. This operation is not possible
return 0;
}
```

Pointer constant means that the pointer cannot be modified. In fact, it can be understood as an ordinary constant, but the value of this constant is an address value, which cannot be modified. In fact, the pointer cannot be modified. Examples are as follows 👇

```int main() {
int x = 1, y = 2;
int* const p = &x;    // constant pointer
p = &y;    // An error is reported. p is a constant. You can't do this
return 0;
}
```

For reference constants, it means that the representative of the reference cannot be modified, that is, it cannot become the alias of other objects, which is actually a reference. A reference is a reference constant, and a reference constant is a reference.
three ️⃣ References are type safe, not pointers. There are more type checks for references than pointers.