[C++ Basic Study Notes] C++ Grammar Reference


quote

reference concept

Reference is not a new definition of a variable, but an alias for an existing variable. The compiler will not open up memory space for the reference variable, it shares the same memory space with the variable it references.

For example: Li Kui, known as "Iron Bull" at home, and "Black Whirlwind"
insert image description here
in the world , which is also the way of aliasing.


How to use citations:

type & reference variable name (object name) = reference entity;

#include<iostream>
using namespace std;
void TestRef()
{
    
    
	int a = 10;
	int& ra = a;//定义引用类型
	cout << a << endl;
	cout << ra << endl;
}
int main()
{
    
    
	TestRef();
	return 0;
}

insert image description here
Note: The reference type must be the same type as the reference entity

& in this place represents a reference, not an address, an operator has multiple meanings, that is, operator overloading.
Note the distinction:
type & means reference (& after the type, such as int& b = a;)
& variable means taking the address (& before the variable, such as int* pa = &a;)
There is no necessary relationship between the two.

insert image description here


Reference properties

1) References must be initialized when they are defined
2) A variable can have multiple references
3) Once an entity is referenced, it cannot refer to other entities (the referenced object cannot be changed)

#include<iostream>
using namespace std;
void TestRef()
{
    
    
	int a = 10;
	int b = 20;
	//int& ra;//该条语句编译时会报错
	int& ra = a;//定义引用变量的时候就需要给其赋初始值
	int& rra = a;//一个变量可以有多个引用
	ra = b;//不能更改引用对象,这句实际上是将b的值赋值给ra

	cout << a << endl;
	cout << ra << endl;
	cout << rra << endl;
}
int main()
{
    
    
	TestRef();
	return 0;
}

insert image description here


often quoted

void TestConstRef()
{
    
    
	const int a = 10;
	//int& ra = a;//该语句编译时会出错,a为常量
	const int& ra = a;
	//int& b = 10;//该语句编译时会出错,b为常量
	const int& b = 10;
	double d = 12.34;
	//int& rd = d;l/该语句编译时会出错,类型不同
	const int& rd = d;
}

When a is of type const int, it means that a is a constant variable, and the constant variable has constant attributes---the value cannot be changed. At this time, if you use int & to refer to a, you will get an alias of type int, which is a common The variable of a can be modified, it may change the value of a, resulting in a conflict that a constant variable is modified! So in order to avoid this conflict, when referencing a variable of type const int, you should use const int& b = a;

Summary: When the reference is aliased, the variable access authority can be narrowed (such as const int -> int ), but cannot be enlarged (such as const int -> int ).
Permissions cannot be enlarged: variables of const type cannot be given to aliases of non-const types.
Permissions can be reduced: that is, variables of non-const types can be given aliases of non-const types and aliases of const types.

Hint: Minification and magnification of permissions, only for references and pointers

const int a = 10;
int* p = &a;//这种不行,权限的放大
const int* pa = &a;//需要这种形式

int c = 1;
const int* pc = &c;//可以,属于权限的缩小

Note the distinction:

const int a = 10;
int& b = a;//这种是不行的,b是a的别名

const int x = 10;
int y = x;//这种是可以的,y和x没什么关系
//这种是不受影响的
#include<iostream>
using namespace std;
int main()
{
    
    
	int i = 1;
	double d = i;//隐式类型转换
	double& ri = i;//可以这样取别名吗? error
	const double& rri = i;//这样呢?ok
	return 0;
}

double d = I; This sentence is to first generate a double temporary variable
double& ri = I; It is also a temporary variable that will first generate a double type, and then the temporary variable is really referenced, and this temporary variable has constant properties , so it is not possible to use double& directly, and it is ok to add const.
insert image description here


scenes to be used

1. Make parameters (①output parameters ②improve efficiency)

#include<iostream>
using namespace std;
void Swap(int& left, int& right)
{
    
    
	int temp = left;
	left = right;
	right = temp;
}

int main()
{
    
    
	int a = 1;
	int b = 2;
	Swap(a, b);
	cout << a << " " << b << endl;
	return 0;
}

insert image description here
Q: Doesn't it mean that initialization is required when referring to a definition? There is no initialization here?
A: The reference in this place is not a definition, when is it a definition? The definition is when the parameter is passed, and the initialization operation will be performed when the parameter is passed.
insert image description here
Of course, this can also be achieved by pointers:

#include<iostream>
using namespace std;
void Swap(int* pa, int* pb)
{
    
    
	int tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}
int main()
{
    
    
	int a = 1;
	int b = 2;
	Swap(&a, &b);
	cout << a << " " << b << endl;
	return 0;
}

insert image description here
2. Do the return value (①Improve efficiency ②I'll ​​talk about it later)

int& Count()
{
    
    
	static int n = 0;
	n++;
	// ...
	return n;
}

insert image description here
Any method of passing by value (parameter passing by value, passing by value and returning) will generate a copy of the temporary variable. Pass-by-reference does not.
static changes the life cycle of the variable without modifying the access rights of the variable


What is the output of the following code? Why?

#include<iostream>
using namespace std;
int& Add(int a, int b)
{
    
    
	int c = a + b;
	return c;
}
int main()
{
    
    
	int& ret = Add(1, 2);
	Add(3, 4);
	cout << "Add(1,2) is : " << ret << endl;
	return 0;
}

insert image description here
Note: If the function returns out of the function scope, if the returned object has not been returned to the system, it can be returned by reference, and if it has been returned to the system, it must be returned by value. (Explain that return by reference is unsafe!)
insert image description here
So what's the benefit of using return by reference?

One less temporary variable can be created to improve the efficiency of the program (transfer)
In fact, there is another function, which will be discussed later (the return of many library functions will also be returned by reference)


Comparison of pass-by-value and pass-by-reference efficiency

With a value as a parameter or return value type, during the parameter pass and return period, the function will not directly pass the actual parameter or return the variable itself directly, but pass the actual parameter or return a temporary copy of the variable, so the value is used as the parameter. Or the return value type, the efficiency is very low, especially when the parameter or return value type is very large, the efficiency is even lower. Performance comparison
of values ​​and references as parameters

#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;
	//以值作为函数参数
	size_t begin1 = clock();
	for (size_t i = 0; i < 1000000; ++i)
		TestFunc1(a);
	size_t end1 = clock();

	//以引用作为函数参数
	size_t begin2 = clock();
	for (size_t i = 0; i < 1000000; ++i)
		TestFunc2(a);
	size_t end2 = clock();
	//分别计算两个函数运行结束后的时间
	cout << "TestFunc1(A)-time : " << end1 - begin1 << endl;
	cout << "TestFunc2(A&)-time: " << end2 - begin2 << endl;
}
int main()
{
    
    
	TestRefAndValue();
	return 0;
}

insert image description here


Performance comparison of value and reference as return value types

#include<iostream>
using namespace std;
#include <time.h>
struct A
{
    
    
	int a[10000];
};
A a;

A TestFunc1()
{
    
    
	return a;
}
A& TestFunc2()
{
    
    
	return a;
}
void TestRefAndValue()
{
    
    
	A a;
	//以值作为函数的返回值类型
	size_t begin1 = clock();
	for (size_t i = 0; i < 1000000; ++i)
		TestFunc1();
	size_t end1 = clock();

	//以引用作为函数的返回值类型
	size_t begin2 = clock();
	for (size_t i = 0; i < 1000000; ++i)
		TestFunc2();
	size_t end2 = clock();

	//分别计算两个函数运行结束后的时间
	cout << "TestFunc1()-time : " << end1 - begin1 << endl;
	cout << "TestFunc2()-time: " << end2 - begin2 << endl;
}
int main()
{
    
    
	TestRefAndValue();
	return 0;
}

insert image description here

Through the comparison of the above code, it is found that the efficiency of passing a value and a pointer as a parameter and returning a value is very different.


Difference between reference and pointer

In terms of syntax, a reference is an alias, which has no independent space and shares the same space with its referencing entity.

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

insert image description here
There is actually space in the underlying implementation, because references are implemented as pointers.

#include<iostream>
using namespace std;
int main()
{
    
    
	int a = 10;
	int& b = a;
	int* p = &a;
	return 0;
}

Let's take a look at the assembly code comparison of references and pointers:
insert image description here
references and pointers are storage addresses

Differences between references and pointers:

1. The reference must be initialized when it is defined, and the pointer is not required
. 2. After the reference refers to an entity at the time of initialization, it cannot refer to other entities, and the pointer can point to any entity of the same type at any time
. 3. There is no NULL reference, but there are 4. NUL pointers
have different meanings in sizeof: the reference result is the size of the reference type, but the pointer is always the number of bytes occupied by the address space (4 bytes under 32-bit platforms)
5. The reference is self-added, that is, the referenced entity Increase by 1, the pointer is self-added, that is, the pointer is offset backward by the size of a type.
6. There are multiple levels of pointers, but there are no multi-level references
. 7. The way to access entities is different. The pointer needs to be dereferenced explicitly, and the reference compiler handles it by itself.
8. Reference Relatively safer to use than pointers

Guess you like

Origin blog.csdn.net/QIYICat/article/details/119843659