用一个例子看const与指针、引用、多级指针结合的区别

#include <iostream>
using namespace std;
class Test
{
public:
Test(int data = 10) :mptr(new int(data)) {}
~Test() {}
//1  返回整型值 ,内置类型的返回值通过寄存器带出。
int GetInt() { return *mptr; }
int GetInt()const { return *mptr; }


//2  返回引用 引用的变量是累作用域,出了这个函数,mptr依然存在,即返回的是*mptr本身
int& GetIntRef() { return *mptr; }
int& GetIntRef()const { return *mptr; }


//3  返回指针,指针类型与内置类型一样,都是值(立即数),通过eax带出,不能取地址
int* GetPtr() { return mptr; }
int* GetPtr()const { return mptr; }


//4  返回指针的引用 返回的是&mptr。
int*& GetPtrRef() { return mptr; } 
int* const& GetPtrRef()const { return mptr; }// int* const *返回引用时,就是在给mptr隐式取地址
/*
返回值类型:int * const *    《==》     mptr类型:int * const *
引用的值ptr   1  已初始化  
 2  可以取地址
 3  是常量 (int * const *)
返回的常引用 int * const &
*/
private:
int *mptr;
/*
在常成员方法中,const修饰的是mptr ,指针本身不能改变 。*mptr可以变。
*/
};
/*
一  检查类型是否匹配
二  是否使用引用 
    2.1 引用是否被初始化
2.2 引用的值能否取地址
2.3 引用的是否是一个常量 
*/
int main4()
{


//4  返回指针的引用 返回的是&mptr。
//int*& GetPtrRef() { return mptr; }
//int* const& GetPtrRef()const { return mptr; }// int* const *

Test t1;
const Test t2;


int *a1 = t1.GetPtrRef();  // int *  =  int *     普通指针 接收  普通引用
int *&b1 = t1.GetPtrRef();   //int *  =  int *     普通引用 接收  普通引用
const int *&c1 = t1.GetPtrRef(); //应该改成 const int * const &c1 = t1.GetPtrRef(); //返回的是&mptr 地址也是立即数,需要用常引用接收 


int *a2 = t2.GetPtrRef();  //???int *  = int * 指针接收 不取地址。
int *&b2 = t2.GetPtrRef();   / 错误  。int* *  != int *  const*   类型不匹配
const int *&c2 = t2.GetPtrRef();// 错误  。const int* * != int *  const*   类型不匹配
//c2(普通)引用一个 指向整型常量的 指针,  右值是一个常指针指向整型变量 的 引用
return 0;
}


int main3()
{


//3  返回指针,指针类型与内置类型一样,都是值(立即数),通过eax带出,不能取地址
//int* GetPtr() { return mptr; }
//int* GetPtr()const { return mptr; }

Test t1;
const Test t2;


int *a1 = t1.GetPtr();  //用mptr给a1初始化。a1指向 mptr指向的内存。
int *&b1 = t1.GetPtr();   ///错的  。b1是普通引用,不能接受立即数,无法取地址
const int *&c1 = t1.GetPtr();//错的  。 const修饰*c1,代表c1指向的是一个整型常量 ,c1本身是普通引用,不能接受 立即数
//int * const &d1 = t1.GetPtr(); const修饰引用,常引用 引用 常量


int *a2 = t2.GetPtr();//返回的类型是 int * ,  类型匹配 
int *&b2 = t2.GetPtr();   /返回指针,指针类型与内置类型一样,都是值(立即数),通过eax带出,不能取地址
const int *&c2 = t2.GetPtr();//同c1一样,c2是普通引用 ,不能引用常量


return 0;
}


int main2()
{
//2  返回引用 引用的变量是类作用域,出了这个函数,mptr依然存在,即返回的是*mptr本身 ,即mptr指向的内存。
//int& GetIntRef() { return *mptr; }  //int *
//int& GetIntRef()const { return *mptr; }  //int *


Test t1;
const Test t2;


int a1 = t1.GetIntRef();//类型匹配, int 接收 int ,相当于用返回值*mptr对a1进行初始化
int &b1 = t1.GetIntRef();   ///即b1是 *mptr的别名
const int &c1 = t1.GetIntRef(); // 常引用 接收一个 普通引用,代表不能通过c1改变*mptr
//不论是常方法还是普通方法 ,返回的都是值,与const无关。const 修饰的是指针mptr


//故以下结果一样
int a2 = t2.GetIntRef();
int &b2 = t2.GetIntRef();   /
const int &c2 = t2.GetIntRef();


return 0;
}
int main1()
{
//1  返回整型值 ,内置类型的返回值通过寄存器带出。
//int GetInt() { return *mptr; }
//int GetInt()const { return *mptr; }
Test t1;
const Test t2;


int a1 = t1.GetInt();  //调用普通方法
int &b1 = t1.GetInt();   //错误  。返回的值是通过寄存器带出,不能取地址,故需要常引用去引用 //int const &b1 = t1.GetInt();  
const int &c1 = t1.GetInt();//用一个临时对象接收寄存器的值,然后对临时对象进行引用


//不论是常方法还是普通方法 ,返回的都是值,与const无关。const 修饰的是指针mptr
//故以下结果一样
int a2 = t2.GetInt(); //调用常方法
int &b2 = t2.GetInt();   //错误  。类型是匹配的 ,但是返回的值是通过寄存器带出,不能取地址,故需要常引用去引用 
const int &c2 = t2.GetInt();//用一个临时对象接收寄存器的值,然后对临时对象进行引用


return 0;
}


/*

错误的类型转换


const int*   =>  int*


const int**  =>  int**
const int*   =>  int*&


int**        =>  const int**
int*         =>  const int*&


int *const**   =>  int***
int***   =>  int *const**

*/



总结:

Const  

Const 修饰的常量 1 必须初始化 2不能做左值。

原因:常量在编译阶段,直接所用地方替换成值。

如果非要修改,可以在代码中嵌入汇编代码,进行修改。

 

Const 与 *

Const与一级指针结合,必须保证不能间接修改常量的值,常量的地址也不能泄露到不安全的人手里,这个不安全的人指普通指针 和普通引用。

Const 修饰指针才参与类型 ,

Const 修饰值 与类型无关 。

 

Const 与 &

Const与引用结合,使用引用时需要考虑三点:

l  引用是否初始化

l  引用的值是否可以取地址

l  引用的是否是常量,如果是常量需要用常引用。

因为常量在编译阶段已是值,不能取地址。立即数同理。

在汇编代码中,常引用即用一个临时变量保存常量的值,然后对这个临时变量进行引用。

 

Const 与**

Const与多级指针结合,少一个const 多一个const都不可以,类型必须完全匹配。


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值