C + + reference 10 minute introductory tutorial

C + + reference 10 minute introductory tutorial

We know that the transfer of parameters is essentially a process of assignment, which is to copy the memory. The so-called memory copy refers to copying data from one memory to another.

For basic types of data such as char, bool, int, float and so on, the memory they occupy is often only a few bytes. It is very fast to copy them in memory. Arrays, structures and objects are a collection of a series of data. The number of data is unlimited, which may be few or thousands. Frequent memory copies of them may consume a lot of time and slow down the execution efficiency of the program.

C/C + + prohibits the direct transfer of array contents during function call, but forces the transfer of array pointers, which has been explained in the previous section. There is no such restriction on structures and objects. When calling functions, you can pass both pointers and contents directly; In order to improve efficiency, I have suggested passing pointers. In most cases, there is nothing wrong with this. Readers can review it.

However, in C + +, we have a more convenient way to transfer aggregate type data than pointers, that is, Reference.

In C/C + +, we call char, int, float and other types supported by the language itself as basic types, and array, structure, class (object) and other types combined by basic types as aggregate types (complex types and structural types have also been used when explaining structures).

Reference is another extension of C + + relative to C language. Reference can be regarded as an alias of data. This data can be found through this alias and the original name. The reference is similar to the shortcut in Windows. An executable program can have multiple shortcuts, and the program can be run through these shortcuts and the executable program itself; Citation is also similar to a person's nickname (pseudonym). Both nickname (pseudonym) and real name can represent a person.

The definition of reference is similar to that of pointer, but with & instead of *, the syntax format is:

type &name = data;

Type is the type of the referenced data, name is the name of the reference, and data is the referenced data. The reference must be initialized at the same time as the definition, and it must be consistent in the future. No other data can be referenced, which is a bit similar to a constant (const variable).

The following is an example of a demo reference:

#include <iostream>
using namespace std;
int main() {
    int a = 99;
    int &r = a;
    cout << a << ", " << r << endl;
    cout << &a << ", " << &r << endl;
    return 0;
}

Operation results:

99, 99
0x28ff44, 0x28ff44

In this example, variable r is the reference of variable a, which is used to refer to the same data; It can also be said that variable r is another name of variable a. It can be seen from the output result that the addresses of a and r are the same, both 0x28ff44; In other words, the memory with address 0x28ff44 has two names, a and r. when you want to access the data on the memory, you can use either name.

Note that the reference needs to be added with &. It cannot be added with &. Adding with & means taking the address. As shown in the above code, the & in line 6 represents a reference, and the & in line 8 represents an address. In addition to these two usages, & can also represent and operations in bit operations.

Since both reference r and original variable a point to the same address, the data stored in the original variable can also be modified by reference. Please see the following example:

#include <iostream>
using namespace std;
int main() {
    int a = 99;
    int &r = a;
    r = 47;
    cout << a << ", " << r << endl;
    return 0;
}

Operation results:

47, 47

Finally, the program outputs two 47. It can be seen that the value of the original variable a has been modified by the referenced variable r.

If the reader doesn't want to modify the original data by reference, you can add const restriction in the form of:

const type &name = value;

It can also be:

type const &name = value;

This way of reference is often cited

C + + references as function parameters

When defining or declaring a function, we can specify the formal parameters of the function as the form of reference, so that the actual parameters and formal parameters will be bound together when calling the function, so that they all refer to the same data. In this way, if the data of the formal parameter is modified in the function body, the data of the actual parameter will also be modified, which has the effect of "affecting the external data of the function inside the function".

As for how parameters and formal parameters are bound, we will discuss in the next section "what is the essence of C + + reference, and what is the difference between it and pointer?" At that time, we will clarify the essence of quotation.

An example that can show the advantages of passing parameters by reference is to exchange the values of two numbers. Please see the following code:

#include <iostream>
using namespace std;
void swap1(int a, int b);
void swap2(int *p1, int *p2);
void swap3(int &r1, int &r2);
int main() {
    int num1, num2;
    cout << "Input two integers: ";
    cin >> num1 >> num2;
    swap1(num1, num2);
    cout << num1 << " " << num2 << endl;
    cout << "Input two integers: ";
    cin >> num1 >> num2;
    swap2(&num1, &num2);
    cout << num1 << " " << num2 << endl;
    cout << "Input two integers: ";
    cin >> num1 >> num2;
    swap3(num1, num2);
    cout << num1 << " " << num2 << endl;
    return 0;
}
//Pass parameter content directly
void swap1(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}
//Pass pointer
void swap2(int *p1, int *p2) {
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}
//Pass parameters by reference
void swap3(int &r1, int &r2) {
    int temp = r1;
    r1 = r2;
    r2 = temp;
}

Operation results:

Input two integers: 12 34↙
12 34
Input two integers: 88 99↙
99 88
Input two integers: 100 200↙
200 100

This example demonstrates three methods of exchanging values of variables:

  1. Swap1() directly passes the contents of parameters, which cannot achieve the purpose of exchanging the values of two numbers. For swap1 (), a and b are formal parameters and local variables whose scope is limited to the function. They have their own independent memory, which is different from the data referred to by num1 and num2. When calling the function, pass the values of num1 and num2 to a and b respectively. Thereafter, num1 and num2 have no relationship with a and b. modifying the values of a and b inside swap1() will not affect num1 and num2 outside the function, let alone change the values of num1 and num2.

  2. What swap2() passes is a pointer, which can exchange the values of two numbers. When calling the function, pass the pointers of num1 and num2 to p1 and p2 respectively, and then p1 and p2 point to the data represented by a and b. the values of a and b can be modified indirectly through the pointer inside the function. We also compared the differences between the methods in 1) and 2) in C language pointer variables as function parameters.

  3. swap3() is passed by reference and can exchange the values of two numbers. When calling the function, bind r1 and r2 to the data referred to by num1 and num2 respectively. Thereafter, r1 and num1, r2 and num2 represent the same data. Modifying the data through r1 will affect num1 and r2 will also affect num2.

From the above code, we can find that passing parameters by reference is more intuitive than pointers in the form of use. In the future c + + programming, I encourage readers to make extensive use of references, which can generally replace pointers (of course, pointers are also indispensable in C + +), and the C + + standard library does the same.

C + + reference as function return value

In addition to being a function parameter, a reference can also be a function return value. See the following example:

#include <iostream>
using namespace std;
int &plus10(int &r) {
    r += 10;
    return r;
}
int main() {
    int num1 = 10;
    int num2 = plus10(num1);
    cout << num1 << " " << num2 << endl;
    return 0;
}

Operation results:

20 20

When using a reference as the return value of a function, you should pay attention to a small problem, that is, you can't return the reference of local data (such as local variables, local objects, local arrays, etc.), because the local data will be destroyed after the function call is completed, and the data may not exist when it is used next time. When the C + + compiler detects this behavior, it will also give a warning.

Change the above example so that plus10() returns a reference to local data:

#include <iostream>
using namespace std;
int &plus10(int &r) {
    int m = r + 10;
    return m;  //Returns a reference to local data
}
int main() {
    int num1 = 10;
    int num2 = plus10(num1);
    cout << num2 << endl;
    int &num3 = plus10(num1);
    int &num4 = plus10(num3);
    cout << num3 << " " << num4 << endl;
    return 0;
}

Run results under Visual Studio:

20
-858993450 -858993450

Operation results under GCC:

20
30 30

Operation results under C-Free:

20
30 0

The operation results we expect are:

20
20 30

plus10() returns a reference to the local variable m, which is the root cause of the very strange running results, because the function runs on the stack, and will give up the management right of all local data after running, and the subsequent function calls will overwrite the local data of the previous function. In this example, the second call to plus10() will overwrite the local data generated by the first call to plus10(), and the third call to plus10() will overwrite the local data generated by the second call to plus10().

Keywords: C++ Back-end

Added by LostOne on Tue, 08 Feb 2022 12:41:19 +0200