“This is the ninth day of my participation in the First Challenge 2022. For details: First Challenge 2022”
C++ references (this blog is the only way I know how to write it)
There is basically no problem with the syntax layer and the bottom layer being separated, but once the two interactive layers are seen, there will be a paradox. Some people say that compiler optimization has forced the optimization of details to be removed. Anyway, it is 3 am now and I have lost my hair and have not realized the details that cause the paradox. There’s a little bit of wave-particle duality in physics, the properties of a wave and the properties of a particle. Syntax layer do find is an alias and ontology public space, but the bottom you will find that he is also a reference variables, that is he has a double word of four bytes (and) pointer variable occupies little space, I understand so such as our computer system is not in the inside of the hard disk, we boot is directly into the system, But there’s actually a little bit of memory in the front of the system that holds the system information like ESP and I don’t remember, but if that thing goes away, your system is disabled, but I don’t think that’s a good example. I have asked many people and no one has explained this little paradox… Bored. C++ is just starting to want my hair
Reference syntax layer
Concept of reference
A reference is an alias for an existing variable. The compiler does not allocate memory for a reference variable (this is syntactic). It shares the same memory space as the variable it refers to
Type & reference variable name (object name) = reference entity
The reference type must be of the same type as the reference entity
Reference features
- References must be initialized at definition time
- A variable can have multiple references
- Reference Once an entity is referenced, no other entity can be referenced
Reference as argument
The value of
/ / value
void Swap(int x, int y)
{
int tmp = x;
x = y;
y = tmp;
}
int main(a)
{
int a = 0, b = 10;
cout << a << endl << b << endl << endl;
Swap(a, b);
cout << a << endl << b << endl << endl;
return 0;
}
Copy the code
The address
/ / reference
void Swap(int* x, int* y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
int main(a)
{
int a = 0, b = 10;
cout << a << endl << b << endl << endl;
Swap(&a, &b);
cout << a << endl << b << endl << endl;
return 0;
}
Copy the code
The reference
/ / reference
void Swap(int& rx, int& ry)
{
int tmp = rx;
rx = ry;
rx = tmp;
}
int main(a)
{
int a = 0, b = 10;
cout << a << endl << b << endl << endl;
Swap(a, b);
cout << a << endl << b << endl << endl;
return 0;
}
Copy the code
Comparison of transmission efficiency between value and reference
In value as a parameter or return value type, the parameter and return period, function not directly arguments passed or returned directly variable itself, but rather pass arguments or returns a temporary copy of the variable, so the use value as a parameter or return value type, the efficiency is very low, especially when the parameter or return value type is very big, efficiency is lower
#include<iostream>
using namespace std;
#include <time.h>
struct A
{
int a[10000];
};
void TestFunc1(A a) {}
void TestFunc2(A& a) {}
void TestRefAndValue(a)
{
A a;
// take a value as a function argument
size_t begin1 = clock(a);for (size_t i = 0; i < 10000; ++i)
TestFunc1(a);
size_t end1 = clock(a);// take a reference as a function argument
size_t begin2 = clock(a);for (size_t i = 0; i < 10000; ++i)
TestFunc2(a);
size_t end2 = clock(a);// Calculate the time after each function finishes
cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
int main(a)
{
TestRefAndValue(a);return 0;
}
Copy the code
Reference to return value
Pass returns All pass returns will generate onecopy
Temporary variables are stored in the smaller 1.c (4 bytes 8 bytes), where the register acts as the temporary variable. 2.C is larger, where temporary variables are placed on the upper stack, such as the stack frame of the Add function here
Pass a reference back
Wrong usage
So how do you use it
Note: If the function returns out of scope, it can return by reference if the object has not been returned to the system. If it has been returned to the system, it must return by pass.
Value and referenced as the return value type
#include<iostream>
using namespace std;
#include <time.h>
struct A
{
int a[10000];
};
A a;
/ / value is returned
A TestFunc1(a) { return a; }
// The reference returns
A& TestFunc2(a) { return a; }
void TestReturnByRefOrValue(a)
{
// The return type of the function is a value
size_t begin1 = clock(a);for (size_t i = 0; i < 100000; ++i)
TestFunc1(a);size_t end1 = clock(a);// use a reference as the return value type of the function
size_t begin2 = clock(a);for (size_t i = 0; i < 100000; ++i)
TestFunc2(a);size_t end2 = clock(a);// Calculate the time after both functions are completed
cout << "TestFunc1 time:" << end1 - begin1 << endl;
cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
int main(a)
{
TestReturnByRefOrValue(a);return 0;
}
Copy the code
Passing values and Pointers are very different in their efficiency as passing parameters and as return value types.
- Reference passing and return values can significantly improve performance in some scenariosLarge object + deep copy object
- Reference pass parameter and return value output parameter and output return valueIt’s a function parameter change that can change the argument outside of the function, and in some cases, when a reference is returned, you can change the object that is returned
Modify the returned object
Readable and writable with the return of a reference
#define N 10
int& fun(const int& i)
{
static int a[N];
return a[i];
}
int main(a)
{
int i = 0;
for (i = 0; i < N; i++)
{
fun(i) = 100 + i;
}
for (i = 0; i < N; i++)
{
cout << fun(i) << "";
}
return 0;
}
Copy the code
Often cited
From the above we can see that const reference size is universal
Const type& can accept variables of various types
This introduces a new problem: the benefits of const referencing parameters
Left value right value
We often have a misconception that the one on the left of the equals sign is called an l-value and the one on the right is called an r-value. This statement is actually not accurate, first of all, lvalues and rvalues are expressions. An lvalue in C++ is defined as a Location Value, which is a Value that can be taken from an address, or a Value that remains after the expression ends. Instead, an rvalue is a temporary value
Don’t think about overstepping your authority. Overstepping your authority is my pet hate
Let’s say that x is a big object or something that’s going to be a deep copy later on and we’ll use a reference argument, so we can reduce the copying and make it more efficient and if we don’t need to change x, we’ll use const references to make our code safer
Refer to the lower
We observed in VS19 that aliases and ontologies are indeed at the same address, so we said that syntax-wise aliases do not make room, but in fact the underlying implementation does, because references are implemented as Pointers.
Playing bottom takes you to see the compilation which is my favorite thing to see
Linux below the authentic assembly can not understand
Difference between a reference and a pointer:
- References are definedMust initializePointer has no requirement
- Reference after referring to an entity during initialization, theYou can no longer reference other entitiesPointers can point to any entity of the same type at any time
- There are no NULL references, but there are NULL Pointers
- It has a different meaning in sizeofThe result of the reference is the size of the reference type, but the pointer is always the number of bytes in the address space (4 bytes on 32-bit platforms)
- Referential autoappend increases the referenced entity by one, and pointer autoappend shifts the pointer back by one type
- There are multilevel Pointers but no multilevel references
- Pointers need to be explicitly dereferenced, which is handled by the reference compiler itself
- References are relatively safe to use than Pointers