【面试常见问题】【C++】指针和引用的区别,有哪些不同点,细细道2

在上一篇中,咱们弄清楚指针和引用的基本区别,下面从「高质量c++编程」的角度剖析指针与引用

一、什么时候用 指针与引用?

  • 首先,有几个意识。
  • Firstly,      任何情况下引用都不能用指向空值,引用必须总是指向某个对象。
  • Secondly, 若用某变量(对象)指向另一个变量(对象),且该变量(对象)具备指向任何对象的能力,这时最好将变量(对象)声明为指针,因为指针可以不指向任何变量(对象
    //空指针(null pointer)不指向任何对象,所以使用指针前一般先进性检查操作,检验指针是否为空:
    // 先介绍3中生成空指针的方法
    int *p1  = nullptr;   // equals to : int *p1 = 0; 【C++11新标准】
    int *p2 = 0; // 直接将指针初始化为字符常量 0
    int *p3 = NULL;   // equals to : int *p3 = 0;
    
    // 后面会紧接着介绍 测空

  • 相反,如果变量肯定指向一个非空变量(对象),这时就把变量声明为引用。下面举一个“毒代码”:
  • char *pc = nullptr;// 设置指针为空值
    char & rc = *pc;// 让引用指向空值 
    这是非常有害的,编译器仍然产生输出,不过,鬼知道结果,这个不确定的输出将摧毁你整个代码大厦(编译器能产生一些输出,导致任何事情都有可能发生)。
  • 另一外测试代码:
  • #include <iostream>
    //#include <vector>
    using namespace std;
    
    void fun( int *x ){
    	x = x + 1;  // 注意这段代码,对指针[而非指针变量]进行加1操作,结果将不可预测
    }
    	
     int main()
    {
    	cout << "请输入1个整数:" << endl;
    	int i1;
    	cin  >> i1;
    	fun( &i1 );
    	cout <<"i1 = " << i1 << endl;
    	system("pause");
    	return 0;
    }




  • 由局部变量变化可知,编译器仍然产生输出,x 本身表示指针的值(地址值),指针值(地址值)+1后对应新的内存单元(地址值),新的内存单元中对应的变量值为{-858993460} = 2^33 - 32;相当于地址变化,但 i1 的值由于对应着固定的内存单元并不发生变化。 

    测试代码继续上:
  •  string &rs;// 错误,引用必须被初始化
     string str("xy32y");
     string &rs = str;// 正确,rs指向s  指针没有这样的限制。
     string *ps;// 未初始化的指针,合法但危险, 应尽量避免
    这也意味着前面一篇文章中所提到的引用的空间和时间优势,时间上更快,占用内存更小。

  •  void printDouble1(double  &rd)   // 这里提一下,引用没有 const,指针有 const; 
    {
         cout << rd; // 不需要测试rd,它肯定指向一个double值
    }
    相反,指针则应该总是被测试,防止其为空:
    void printDouble2(const double *pd)
    {
         if (pd)  // if (true)  若非空指针,即指针指向一个内存单元
         { // 检查是否为NULL
               cout << *pd;
         }
    }

    指针可以被重新赋值以指向另一个不同的对象引用can only指向在初始化时被指定的对象,不能改变
  • string s1("Nancy");
    string s2("Clancy");
    string &rs = s1; // rs 引用 s1
    string *ps = &s1; // ps 指向 s1
    rs = s2; // rs 仍旧引用s1, 但是rs传递的是实参, 故s1的值被赋值为"Clancy"
    ps = &s2; // ps 现在指向 s2; 喜新厌旧,换了新对象

    小结:一 存在不指向任何对象的可能(在这种情况下,你能够设置指针为空)=>指针
  •   二 在不同的时刻指向不同的对象(在这种情况下,你能改变指针的指向)=>指针
  •           三 总指向一个对象,且之后不改变指向 => 引用
  •   四 重载某个操作符 = > 引用
  • 重点拆解一下
  • 最普通的例子是操作符[].这个操作符典型的用法是返回一个目标对象,其能被赋值。
  • vector<int> v(10); // 建立整形向量(vector),大小为10;
    // 向量是一个在标准C库中的一个模板(见条款35)
    v[5] = 10; // 这个被赋值的目标对象(变量)就是操作符[]返回的值
    如果操作符[]返回一个指针,那么后一个语句就得这样写:
    *v[5] = 10;
    但是这样会使得v看上去象是一个向量指针。因此你会选择让操作符返回一个引用。(这有一个有趣的例外,参见条款30)
    当必须指向一个对象且不改变其指向时,或者在重载操作符并为防止不必要的语义误解时,应使用引用。而在除此之外的其他情况下,则应使用指针
    void fun(int *p, int &r);
    int a = 1;
    int b = 1;
    fun(&a, b);


  • 指针本身的值(地址值)是以passby value进行的,你能改变地址值,但这并不会改变指针所指向的变量的值
    p = some other pointer;// 起始地址值随机值, 右移一位后地址值改变一个int型长度4 Byte, 输入的整数位333, i1 依旧为 333【见图一】
    但能用指针来改变指针所指向的变量的值,
  • 倘若红线处 修改为“ *x = *x +1 ”, 则有
    *x = 333+1; // 且指针所指变量 i1 将也加1 变为 334【见图二】
  • 如下面两个图:
  • 图一
  • 图二


  • 摘自《「高质量c++编程」》,不过下面这些着实是等到使用者达到一定经验才会遇到。
  • 尽可能使用引用,实在不得已,使用指针。
  • 引用出现的典型场合是对象的表面,而指针用于对象内部。
    当你不需要“重新指向”时,引用一般优先于指针被选用。这通常意味着引用用于类的公有接口时更有用,不过博主真的很喜欢这句话,“程序员 应该针对要解决的问题写代码,而不是不经思考的套娃,高效,简洁,质优才是一个程序员应该追求的”


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值