“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

image-20211206203633555


Type & reference variable name (object name) = reference entity

The reference type must be of the same type as the reference entity

Reference features

  1. References must be initialized at definition time
  2. A variable can have multiple references
  3. Reference Once an entity is referenced, no other entity can be referenced
image-20211206211028288


Reference as argument

The value of

image-20211206231602873


/ / 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

image-20211206233026964


/ / 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

image-20211206234230844


/ / 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
image-20211207000454304


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

image-20211207154228580


#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

image-20211208075406647


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

image-20211207124631634


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

image-20211207173215487


#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.

  1. Reference passing and return values can significantly improve performance in some scenariosLarge object + deep copy object
  2. 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

image-20211207212645153


#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
image-20211207213851417


Often cited

image-20211207182559488


image-20211207234808535


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

image-20211208002223513


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

image-20211207185336905


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

image-20211207190827538



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

image-20211208015114991


Linux below the authentic assembly can not understand

image-20211208015655043


Difference between a reference and a pointer:

  1. References are definedMust initializePointer has no requirement
  2. 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
  3. There are no NULL references, but there are NULL Pointers
  4. 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)
  5. Referential autoappend increases the referenced entity by one, and pointer autoappend shifts the pointer back by one type
  6. There are multilevel Pointers but no multilevel references
  7. Pointers need to be explicitly dereferenced, which is handled by the reference compiler itself
  8. References are relatively safe to use than Pointers