目录
通过汇编分析指针
void pointerNature(void){
int age = 3;
int *p = &age;
*p = 5;
/**
0x100009c40 <+0>: pushq %rbp
0x100009c41 <+1>: movq %rsp, %rbp
//将立即数 0x3 放入地址 -0x4(%rbp)
-> 0x100009c44 <+4>: movl $0x3, -0x4(%rbp) //-0x4(%rbp)变量age的地址;int age = 3;
//将地址 -0x4(%rbp) 放入寄存器 %rax
0x100009c4b <+11>: leaq -0x4(%rbp), %rax //&age 放入寄存器rax; rax = &age;
//将寄存器内的内容放入地址 -0x10(%rbp)
0x100009c4f <+15>: movq %rax, -0x10(%rbp) //-0x10(%rbp)变量p的地址; int * p = rax;
//将地址-0x10(%rbp)内的内容放到寄存器%rax
0x100009c53 <+19>: movq -0x10(%rbp), %rax // rax = *p = &age;
//将立即数$0x5放入 寄存器(%rax)内存放的地址
0x100009c57 <+23>: movl $0x5, (%rax) // rax=*p=&age=5;
0x100009c5d <+29>: popq %rbp
0x100009c5e <+30>: retq
*/
}
通过汇编分析引用
void referenceNatureByAssembly(void){
int age = 3;
int &p = age;
p = 5;
/**
0x100009c40 <+0>: pushq %rbp
0x100009c41 <+1>: movq %rsp, %rbp
-> 0x100009c44 <+4>: movl $0x3, -0x4(%rbp)
0x100009c4b <+11>: leaq -0x4(%rbp), %rax
0x100009c4f <+15>: movq %rax, -0x10(%rbp)
0x100009c53 <+19>: movq -0x10(%rbp), %rax
0x100009c57 <+23>: movl $0x5, (%rax)
0x100009c5d <+29>: popq %rbp
0x100009c5e <+30>: retq
*/
//汇编代码与指针的汇编代码 一模一样,引用的本质就是指针
}
其它数据类型的引用
struct Date{
int year;
int month;
int day;
};
void referenceWithOtherType(void){
//1、结构体的引用
Date d = {2011,2,1};
Date &ref = d;
ref.year = 2012;
cout<<"d.year = "<<d.year<<endl;
//2、指针的引用
int age = 10;
int * p = &age;
int * & ref2 = p;
int height = 180;
ref2 = &height;
cout<<"*ref2 = "<<*ref2<<endl;
cout<<"*p = "<<*p<<endl;
//3、数组
{
int array[3] = {1,2,3};
int * a = array;
}
{
//指针数组,数组里面可以存放3个int *
int age1 = 10, age2 = 20 , age3 = 30;
int *ap1 = &age1 , *ap2 = &age2 , *ap3 = &age3;
int * array[3] = {ap1,ap2,ap3};
int ** a = array;
}
{
//指向数组的指针
int array[3] = {1,2,3};
int (*p)[3] = &array;
}
//4、数组的引用
{
int array[3] = {1,2,3};
//方式一:
int (&ref)[3] = array;
//方式二:
int * const & ref2 = array;//array是数组的首地址是一个常量
ref[1] = 4;
cout<<"array[1] = "<<array[1]<<endl;
cout<<"ref[1] = "<<ref[1]<<endl;
cout<<"ref2[1] = "<<ref2[1]<<endl;
}
{
int age = 10;
int ageRef = age;
//不存在引用数组
//int& array[3] = {ageRef,ageRef,ageRef};
}
//5、不存在引用的引用
{
int age = 10;
int &refAge = age;
//int &&rrAge = ref;//错误不存在引用的引用
}
}
常引用
int constRefTest(const int &a){
//函数内部不可对a进行修改,保护变量a
//a = 20;
return a+10;//可以访问
}
int pointerTest(const int* a){
//函数内部不可更改变量a存储的内容,保护变量a
//*a = 20;
return *a+10;//可以访问
}
void constReference(void){
//1
int age = 10;
const int &ref = age;
//ref = 20;//常引用,不可对ref赋值
/**
因为引用的本质是指针
const int & ref = age;
const int * ref1 = &age;
ref 相当于 *ref1,*ref1 不可修改,所以 ref不可修改
int const & ref 与 const int & ref 相同
*/
//2
//int & const reff = age;//报错可能是有的编译器不支持
//reff = 20;//可以修改
/**
因为引用的本质是指针
int & const reff = age;
int * const reff1 = *age;
reff可以修改,就类似与 *reff1可以修改一样
*/
}
常引用可以指向临时变量
指向临时变量
int sumTest(int a,int b){
return a+b;
}
void constReferenceTemp(void){
//1、常引用可以指向临时变量
{
//int &ref = 30;//报错
const int &reff = 30;
//reff = 20;//因为是常量不可修改
cout<<"reff = "<<reff<<endl;
}
//2、常引用指向函数返回值
{
//返回值int 是一个常量
//int & ref = sumTest(1, 2);
const int & reff = sumTest(1, 2);
//reff = 4;//因为是常量不可修改
cout<<"reff = "<<reff<<endl;
}
//3、
{
int age = 10;
const int &ref = age;
//ref = 30;//不可更改
age = 30;//可以修改
cout<<"age = "<<age<<endl;//30
cout<<"ref = "<<ref<<endl;//30
}
//4、
{
int age = 10;
//引用指向了不同的类型,需要用const
//long & ref = age;
//当常引用指向了不同类型的数据时,会产生临时变量,所以修改age不会更改reff的值
const long & reff = age;
cout<<"reff = "<<reff<<endl;//30
age = 40;
cout<<"age = "<<age<<endl;//40
cout<<"reff = "<<reff<<endl;//30
}
}
作为参数
/**
可以接受常量,const修饰的变量,非const修饰的变量
const修饰传递的参数范围比较大
*/
int sumTest2(const int&a,const int&b){
cout<<"int sumTest2(const int&a,const int&b)"<<endl;
return a + b;
}
/**
const 修饰引用或指针(本质相同)作为参数时,可构成重载
const 修饰非引用或非指针时不构成重载
*/
int sumTest2(int &a,int &b){
cout<<"int sumTest2(int &a,int &b)"<<endl;
return a+b;
}
void constReferenceTemp2(void){
//非const修饰的变量
int a = 10;
int b = 20;
sumTest2(a, b);
//const 修饰的变量
const int a1 = 10;
const int b1 = 20;
sumTest2(a1, b1);
//非const修饰的变量
int & refa1 = a;
int & refb1 = b;
sumTest2(refa1, refb1);
//const 修饰的变量
const int &refa2 = a;
const int &refb2 = b;
sumTest2(refa2, refb2);//如果函数参数去掉const 此处调用会报错
}
行者常至,为者常成!