C++基础入门(2)

int main()
{
  int a=10,b=20;
  int * const p=&a;
  int  *s1=p;
  const int *s2=p;
  int *const s3=p;
  const  int  *const s4=p;
}

在这其中s1,s2,s3,s4都可以编译通过,因为s1,s2,s3,s4的改变都不会影响p自身的值进行改变。

一.引用

int a=10;
const int b=20;

C++11中给出了值的类别

左值引用与右值引用

左值:能取地址(左值引用)

右值:不能取地址(右值引用)

在上述代码中,a 是左值,b也是左值,10不可取地址,是右值。

int a=10;
int &ra=a;//1
const int &ra=a;//2
int  &&rra=a;//3
int  &&rra=10;//4

1中,是普通左值引用

2常性左值引用

3中 &&rra是右值引用,a是左值

所以不可编译通过,要给右值

4正确,&&rra是右值引用,不是等级引用

1.将亡值

这个值只存在于表达式计算过程中。(判断其为左值或右值的方法为:看其有无名字,有名为左值,无名为右值)

int main()
{
  int a=10;
  int b=20;
  int c=0;
  c=a+b;//在这个过程中会开辟一块临时空间累加a和b,这块临时空间中的值赋给c,在这条代码运行完后临时空间值销毁,只存活于加法运行过程中,这个就称为将亡值。

}

由内置类型(char,int,double等不是自己设置)计算过程中产生的亡值具有常性,只可读不可写。

2.const引用(万能引用) 

int main()
{
  int a=10;
  const  int b=20;
  int  &ra =a;//ok
  const int &cra =a;//ok
  int &rb =b;//error,与常性冲突
  const int *crb =b;
  const int  &rc =100;
  //int tmp =100;
  //const int &rc=tmp;//rc=100;
  int  &&rrc=100;//int tmp=100 int &&rrc=tmp;
  rrc=200;//左值引用
}

由上 可得:

普通变量可以初始化普通引用,也可以初始化常引用。

常性只能初始化常引用。

常性左值引用不仅可以引用变量也可以引用右值常量。

int  &&rrc=100;

从上述代码中提取的这行代码

是具名的右值引用

再次使用rrc引用,只能用左值,不能用右值。

3.引用作为形参代替指针

可以用 引用代替指针(不用判定)

但引用的灵活性较差

4.其他引用形式

引用数组:用类型加元素来说明数组

int main()
{
  const int n=10;
  int ar[n]={12,23,34,45,56,67,78,89,100};
  int (&br)[n]=ar;//引用数组
  cout<<sizeof(ar)<<endl;
}

引用指针

int main()
{
  int a=10,b=20;
  int *p=&a;
  int *s=p;
  int  *&rp=p;//引用指针
  *rp=100;
  rp=&b;
}

5.指针与引用的区别

语法规则:

从语法规则上讲,指针 变量储存某个实例(变量或对象)的地址;引用是某个实例的别名。

程序为指针变量分配内存区域。

解引用是指针使用时要在前加“*”;引用可以直接使用。

指针变量的值可以发生改变,储存不同实例的地址;引用在定义时就被初始化,之后无法改变(不能是其他实例的引用)。

指针变量的值可以为空(NULL,nullptr);没有空引用。

指针变量作为形参时需要测试它的合法性(判空NULL);引用不需要判空;

对指针变量使用“sizeof"得到的是指针变量的大小。对引用变量使用“sizeof”得到的是变量的大小。理论上指针的级数没有限制;但引用只有一级。即不存在引用的引用,但可以有指针的指针。++引用与++指针变量的效果不一样。

例如就++操作而言,对指针变量的操作,会使指针变量指向下一个实体(变量或对象)的地址;而不是改变所指实体(变量或对象)的内容。对引用的操作直接反应到所引用的实体(变量或对象)。

5.1引用作为函数的返回值类型

函数调用分配栈区,不调用就不分配。

eax:累加器 ebx:基址寄存器 ecx:计数器 edx:数据寄存器。

CPU中寄存器都有什么作用?

1. 用于传送和暂存数据,可以提高程序的运行速度。它们可以直接将运算结果存放在寄存器中,避免了转存到存储器的时间,从而提高了程序的运行速度。
2. 参与算术逻辑运算,并保存运算结果。通用寄存器可以作为CPU运算过程中的数据和指令的存放单元,为程序设计提供方便。
3. 具有特殊功能。例如,AX和AL通常称为累加器(Accumulator),用于乘、除、输入/输出等操作;BX称为基地址寄存器(Base Register),可作为存储器指针使用;CX称为计数寄存器(Count Register),用于控制循环次数;DX称为数据寄存器(Data Register),用于存放I/O的端口地址等。
需要注意的是,汇编语言程序员必须熟悉每个寄存器的一般用途和特殊用途,才能在程序中做到正确、合理地使用它们。

汇编中指令的意思:

MOV:传送指令       mul:   乘法指令

div:除法指令             jmp:转移指令

call:过程调用指令,调用子程序    ret:将程序从子程序返回到主程序

lea:地址传送指令      push:进栈指令     

pop:从栈中弹出数据并赋给一个寄存器的指令

add:加法指令          sub:减法指令

汇编中寻址方法

汇编语言的七种寻址方式如下:
1. 立即寻址方式:操作数直接包含在指令中,紧跟在操作码之后。例如:MOV AL, 6。
2. 寄存器寻址方式:操作数直接包含在寄存器中,由指令指定寄存器号。例如:MOV BX, AX。
3. 直接寻址方式:操作数的有效地址直接包含在指令中。例如:MOV AL, 。
4. 相对寻址:目标地址 = PC当前值 + 跳转指令字节数 + rel,仅在转移指令中使用。
5. 变址寻址:以DPTR或PC作为基址,累加器A为变址,并将两者内容相加形成的16位地址作为操作数地址。例如:MOVC A, @A+DPTR。
6. 位寻址:操作数是内部RAM 20H-2FH单元中的位(007FH)或者SFR中具有位地址的某一位。例如:MOV C, 20H。
7. 寄存器间接寻址:以寄存器中的内容为地址,以该地址中的内容为操作数。MCS-51规定R0或R1为间接寻址寄存器。例如:MOV A, @R0。
以上每种寻址方式都给出了一个汇编语言的例子。

Linux中栈有10照  Windows中栈有1照

esp管理栈顶

ebp管理栈底

int *func()
{
  int ar[5]={1,2,3,4,5};
  return &ar[1];
}
int main()
{
  int *p=func();
  printf("p=%d\n",*p);
  printf("p=%d\n",*p);
  return 0;
}

是错误的

因为不可以对函数中局部变量或对象以引用或者指针方式返回。

什么情况可以将变量地址以指针或引用方式返回?

变量不受函数影响。全局变量

5.3 分析效率

struct Student
{
  char s_id[20];
  char s_name[20];
  char s_sex[8];
  int s_age;
}

void funa(struct Student sx)//56  值类型
{}
void funb(struct Student *ps)//4  指针类型
{}
void func(struct Student& st)//4  引用类型
{}

在定义过程中不能三个随便挑一个设置,要根据不同类型优缺点设置。

总结:引用返回的值/指针返回的地址,生存期不受函数影响就可以返回。 

 

  • 14
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值