1.引用的本质
struct typeA
{
  int &a;
}
struct typeB
{
  int *a;
}
int main(void)
{
  cout<<sizeof(struct typeA)<<endl;//输出4
  cout<<sizeof(struct typeB)<<endl;//输出4
  int a =10;
  int &re =a;//常量要初始化,引用也要初始化,引用可能是一个常量
  //综上两点,引用可能是一个常指针;
  int *const p=&a;//常指针
}
//引用占用的大小和指针是一样的

struct student
{
  int id;
  char name[64];
}

//修改a所指向量的值
void motify(int *const a)
{
  *a=300;
  a++;//这个是不可以的,可以改变a的值,不能改变a的方向。
}
//修改a所指向量的值
void motify2(int &a)
{
  a=300;//对一个引用赋值的时候,编译器替我们隐藏*操作
}
//
int main(void)
{
  int a = 2;
  motify(&a);//因为引用就是常指针
  motify2(a);//当我们将引用作为函数参数传递时,编译器,会替我们将实参,取地址给引用
}
//在研究引用的时候,可以将引用当做一个指针常量去研究
//当使用引用的时候,将引用当做变量的别名
//总体来说,在作为形参的时候,将引用作为常指针,并且做操作的时候,编译器会隐藏*(取内容运算)操作,直接a=...;
//在作为实参的时候,编译器会隐藏&(取地址运算)操作。

2.常量
在C++中,有分常量区和栈。
int array[10];//在栈中开辟10个int的空间,在常量区放置array名字的变量,值是这10个int的第一个地址。
int &r=a;//在常量区放置一个r名字的变量,值是栈中a的地址

3.引用作为函数的返回值
int getA1()
{
  int a=10;
  return a;//拷贝a的值,并返回,a被销毁
}
int& getA2()
{
  int a=10;
  return a;//返回一个const int &temp=a;
}
int main(void)
{
  int a =0;
  a= getA1();//拷贝getA1中的a值
  int mian_a=10;
  mian_a=getA2();//mian_a=temp,temp是a的别名,数值拷贝,如上,隐藏了*操作,操作完这步,a才会被销毁
  int &mian_a_re=getA3();//又将temp赋值给main_a_re,a的别名变为mian_a_re,a没有被销毁
  //如果对mian_a持续往下操作,mian_a(常指针)所指向的值将会不正常,因为局部变量a本该被销毁的,因为a的方法栈中。
}
//如果引用作为返回值,不要返回局部变量的引用。
***
int& getA3()
{
  static int a = 10;//这里倒是可以这样,因为static是另外开辟空间的。而且这句只会被执行一次。
  return a;
}
//当然也可以getA3()=1000;来搞,因为getA3()相当于int *const temp,但是编译器在赋值和取值,又会帮忙*temp

4.指针引用
struct teacher
{
  int id;
  char name[64];
}
int get_men(struct teacher** tpp)
{
  struct teacher *tp=NULL;
  tp=(struct teacher*)malloc(sizeof(stuct teacher));
  //malloc是动态申请一块内存,并返回*void指针,*void指针相当于未确定类型的指针
  if(tp==null)
  {
    return -1;
  }
  tp->id=100;
  strcpy(tp->name,"LaoWang");
  *tpp=tp;//赋值
  return 0;
}
//跟上面a不一样了,因为malloc是申请的内存,要手动释放才释放,而a作为局部变量,方法执行完要自动释放
void free_teacher(struct teacher **tpp)//tpp是指向指针的指针
{
  if(tpp==NULL)
  {
    return;
  }
  struct teacher *tp=*tpp;//对tpp进行*tpp,取得的是指向teacher的指针
  if(tp!=NULL)
  {
    free(tp);
    *tpp=null;//还要记得搞掉*tpp的指向
  }
}
****不作struct teacher的结构体拷贝,纯粹使用指针完成,struct teacher实际只开辟了一次内存
int main(void)
{
  struct teacher *tp=NULL;
  get_mem(&tp);//tp本来是指针,再&一次,就是指向指针的指针。
  //...
  free_teacher(&tp);
}
以下使用引用方式地址传递:
int get_mem2(struct teacher * &tp)//指向teacher*(指向teacher的指针)的常指针,使用时,按指向teacher的指针的别名
{
  tp=(struct teacher*)malloc(sizeof(struct teacher));
  if(tp==NULL)
  {
    return -1;
  }
  tp->id=100;
  strcpy(tp->name,"LaoWang");
  return 0;
}
void free_teacher2(struct teacher *&tp)//相当于const struct teacher **tp,在使用时,tp当作是一个指向struct teacher的指针变量的别名。
{
  if(tp!=NULL) //相当于*tp,编译器自动取进行*取内容运算
  {
    free(tp);
    tp=NULL;
  }
}
int main(void)
{
  struct teacher *tp=NULL;
  get_mem2(tp);//编译器自动取地址操作&,传入的是指向(指向tp的指针),二级指针
}
//助记,使用时,分两部分看
类型A B;
类型A &dd=B;
//dd是类型A的变量的别名,对dd操作,相当于对变量本身的操作,无论传到哪里都好;
Function(typeA &p);
//使用引用传递,没有内存开辟。
//调用
typeA a=....;
Fuction(a);
//填写typeA变量,那么p代表a,操作p等于操作a;
E.g 如果typeA是指针型变量,那么操作p相当于操作一个指针。
typeA &Function()
{
  typeA a=...;
  Return a;
  //语法上,返回一个typeA型变量,实际上返回a本身。
  //不用引用时,是返回a的copy(释放内存又开辟内存),而引用,这是a本身,(释放内存又强行返回引用,如果a是局部变量)
  //所以不要返回局部变量的引用
}
typeA &p=Function();
//操作p就相当于操作a本身,free(&p)就相当于free(&a)本身,&是取地址运输,&a相当于typeA*型。
//引用是个奇特的东西,介于常指针和变量之间

5. const引用
const引用常用于函数形参
void function()
{
  const int a =10;
  int &re=a;//报错,如果想对常量进行引用,必须使用const引用,因为re的安全性高于a
  const int &re=a;//不报错
  int b =20;
  const int &re2=b;//不报错 ,用比较安全的re2来引用不那么安全的b是可以的
  re2=300;//报错,按理re2是b的别名,对其操作相当于对b操作,但这里不行,所以常用于函数形参以提高内存效率,并且保护原值。
}
//
//方法执行时,产生的临时变量放在栈(根据内存的用途,对内存的称呼)中,当方法执行结束后,在执行其他方法时,上一个方法开辟的内存就会被做其他用途,这个过程叫“压栈”
//
void main()

{

  //(1)变量初始化,再const引用 变量

  int b = 10;

  const int &a = b;

  b = 11;//b是可以修改的,但是a不能修改

  printf("a=%d,b=%d\n", a, b);
  //最终输出a和b都是11,证明a依然代表b,只是不能通过a修改b
  system("pause");

}
6. const引用和const函数
class A
{
  public:
  int getLenght1()//实际上会编译为 int getLenght(int *const this),const指针,指向不可变
  {

  }
  //
  int getLenght2() const //实际上为const int *const this,相当于const引用,指向内容不可变,指向不可变 , 相当于const A &a
  {

  }
}

// 不能通过const引用修改变量的值
void function(const A &a) //为了保护a不在方法中被改变
{
  a.getLenght1(); //这里出错,用高安全的引用作为实参,调用低安全形参的函数。
  a.getLenght2(); //这里才不会出错
}

7.
const变量:const int a;
指向const变量的指针: const int *a;
const指针:int *const a
(助记,const离那个近,那个就“常”)

8. 标明为const的变量,在const区有独立的地址

int main(void)

{

  const int a =1;

  int *p=(int * )&a;

  *p=10;//在C语言中,a的变量已经变为10了;但是在C++中,a的独立在const区那部分的内存的,&a操作,实质是上是开辟一个临时变量,将地址给P了。

}

C++学习笔记1_ 指针.引用的更多相关文章

  1. Dubbo -- 系统学习 笔记 -- 示例 -- 泛化引用

    Dubbo -- 系统学习 笔记 -- 目录 示例 想完整的运行起来,请参见:快速启动,这里只列出各种场景的配置方式 泛化引用 泛接口调用方式主要用于客户端没有API接口及模型类元的情况,参数及返回值 ...

  2. 吴裕雄--天生自然C++语言学习笔记:C++ 引用

    引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字.一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量 C++ 引用 vs 指针 引用很容易与指针混淆,它们之间有三个主要的 ...

  3. Linux学习笔记1_用户和权限

    自从我大微软终于放下身段,决定给开源社区一个迟来的拥抱,追随多年的拥趸们像是突然得到了女神的垂青,各种茫然失措.痛哭流涕.欢欣鼓舞,纷纷唱了起来:“等了好久终于等到今天,梦了好久终于把梦实现……”唱完 ...

  4. 《C语言学习笔记》指针数组及其应用

    C语言中,最灵活但又容易出错的莫过于指针了.而指针数组,是在C中很常见的一个应用.指针数组的意思是说,这个数组存储的所有对象都为指针.除了存储对象为指针,即一个地址外,其它操作和普通数组完全一样. # ...

  5. c++学习笔记——智能指针

    智能指针是为了便于管理动态内存,能够自动管理释放所指向的对象. 智能指针共有三种:1.shared_ptr允许多个指针指向同一个对象:2.unique_ptr独占所指向的对象:3.weak_ptr是一 ...

  6. C++学习笔记29,引用变量(1)

    引用变量在创建的时候就必须初始化.无法创建一个未被初始化的引用. #include <iostream> using namespace std; int main() { int x=1 ...

  7. JS学习笔记1_基础与常识

    1.六种数据类型 5种基础的:Undefined,Null,Boolean,Number,String(其中Undefined派生自Null) 1种复杂的:Object(本质是一组无序键值对) 2.字 ...

  8. JavaScript学习笔记1_基础与常识

    1.六种数据类型 5种基础的:Undefined,Null,Boolean,Number,String(其中Undefined派生自Null) 1种复杂的:Object(本质是一组无序键值对) 2.字 ...

  9. go学习笔记-语言指针

    语言指针 定义及使用 变量是一种使用方便的占位符,用于引用计算机内存地址.取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址. 一个指针变量指向了一个值的内存地址.类似于变量和常量, ...

随机推荐

  1. js 验证数据类型的4中方法

    1.typeof  可以检验基本数据类型 但是引用数据类型(复杂数据类型)无用: 总结 : typeof  无法识别引用数据类型  包括 bull; 2.instanceof是一个二元运算符,左操作数 ...

  2. Java 学习笔记之 Synchronized锁重入

    Synchronized锁重入: 当一个线程得到一个对象锁后,再次请求此对象锁时是可以再次得到该对象的锁.这也证明在一个Synchronized方法/块的内部调用本类的其他Synchronized方法 ...

  3. 快学Scala 第四课 (多维数组,与Java集合的互操作)

    Scala二维数组的定义: val arr2 = Array.ofDim[String](2, 2) arr2(0)(0) = "aa" arr2(1)(0) = "bb ...

  4. Laravel 5 中文文档 CHM 版

    使用 Microsoft HTML Help Workshop 做了一个 Laravel 5.4 中文文档的 CHM 版本. 百度网盘下载地址:http://pan.baidu.com/s/1dFN2 ...

  5. Java运算符及优先级(全)

    运算符是一种特殊的符号,用以表示数据的运算.赋值和比较等. Java运算符分为以下几种: • 算术运算符:+,-,*,/,%,++,-- • 赋值运算符:= • 扩展后的赋值运算符:+=,-=,*=, ...

  6. SDI接口基于FPGA GTP实现

    SDI采集和显示,基于xilinx 7系列器件进行实现,注意事项有如下几点: 1,如果多路SDI共用一个GTP Quad,或是SDI和PCIE在一个GTP Quad,时钟资源应该进行共享,既GTP c ...

  7. python编程基础之三

    变量 变量定义:变量名 = 值  #不需要给定变量类型 变量命名规范:也就是标识符的命名规则, 1.由数字,字母,下划线组成,不允许数字开头 2.区分大小写 3.不能是系统保留字(keyword) 获 ...

  8. Java11月9日的动手动脑

    Java动手动脑 请自行编写代码测试以下特性(动手动脑): 在子类中,若要调用父类中被覆盖的方法,可以使用super关键字. 程序源代码: package yanzhengjicheng; class ...

  9. PHP array_pop

    1.函数的作用:删除数组的最后一个元素并返回 2.函数的参数: @params array &$array 3.注意点: 每次调用之后,重置指针 4.例子: <?php $product ...

  10. vue-cli3 关闭一直运行的 /sockjs-node/info?t= ...

    首先 sockjs-node 是一个JavaScript库,提供跨浏览器JavaScript的API,创建了一个低延迟.全双工的浏览器和web服务器之间通信通道. 本地项目运行就会自动去访问:http ...