cpp reference and function

栏目: C++ · 发布时间: 6年前

内容简介:在cpp 里面这里 *, & 和实际使用到 *p, &a 的时候是不一个意思的, 在定义变量类型的时候 *, & 是没有任何意义的, 表示的只是这个一个指针类型, 和引用类型**函数前面的 *, & 和变量声明的 *, & 一个意思, 只是表示这个函数返回值的类型. **

在cpp 里面

int *p;
int &r;

这里 *, & 和实际使用到 *p, &a 的时候是不一个意思的, 在定义变量类型的时候 *, & 是没有任何意义的, 表示的只是这个一个指针类型, 和引用类型

**函数前面的 *, & 和变量声明的 *, & 一个意思, 只是表示这个函数返回值的类型. **

函数的return val; 这里这个val 无论是 *val, &val 都不影响这个函数的声明, 这个是函数的使用者不需要关注的, 也可以理解, 因此这个return val 属于函数的实现里面, 不属于函数的声明

在这里我们要知道 &(reference) 是cpp 新加入的一种类似, 和指针一样表示的是引用类型而同时& 也是用来做取地址操作, 因此容易混淆.

int a = 10;
int &r = a; // 这里& 是声明r 是一个引用类型
int *p = &a; // 这里& 是取地址操作

传给函数的时候什么时候用 &, 什么时候用 * 呢?

  1. 如果这个参数可以是NULL, 那么只能必须用 pointer, 否则就可以用&
  2. 为了方便起见传入的参数用&, 可能被修改的用*

reference 一旦订下来 就不能修改, 比如 int &b = a; 接下来就不能把这个b 又成为别人的引用, 因为引用的意思就是别名(an alternate name), 不能说b 既是a的别名, 也是c 的别名

所以从这个角度来说 & 和 int* const p 是一样的(注意和const int *p 的区别, const int *p 表示的是这个int 是const, 所以是不能对这个这个int 进行修改, 但是p 可以指向其他地址. 而int * const p 是p 是一个const 指针, 指向一个非const 的int. 可以对这个 *p = new value的, 但是不能让 p = new address, 因为就和引用一样, 是不能又成为一个新的值的引用的.)

常见的函数和reference 几个问题

  1. 函数的定义前面加上 &

  2. 函数的定义前面加上 *

    • 上面两个其实结果是一样的, 函数前面的 &, * 其实有点类似于变量的声明时候的&, * 的用途, 表示的都是没用任何意义. 只是声明这个函数的返回值是 reference 类型和指针类型. 在函数的返回 return val, 如果变成 return *val, return &val 都是没有任何影响的, 就好像外部对这个val 一无所知, 只有函数前面的 int &, int, int * 来描述这个return val 是什么意思一样. 所以 重要 重要 函数前面的 *, & 和变量声明的 *, & 一个意思, 只是函数返回值的类型. 所以其实函数可以看成

      int* fun() {
        .... // 中间这里是不用关注的
        return val; // 这里变成return *val, return &val 都没有任何的影响
      }
      这就类似于 int *val;
           
      那么要接这个val 就必须是
      int *p = fun(); // 因为这里 fun() 就是一个val. 而val 就是 int *类型.
      // 或者这里函数的定义 int *fun() 就告诉了这里是int * 类型的意思
      
    • 函数的返回结果如果是& 的时候, 接这个函数的返回结果的变量必须定义成reference 类型. 就跟如果函数返回前面 *, 接这个函数的返回结果的变量必须定义成pointer 类型一样.

  3. 函数的返回结果是const(其实把函数的声明看成变量的声明就清晰了)

    1. 一般函数的返回是引用或者指针的时候才有必要加上const, 表示的是对这个返回结果的一个保护, 不能修改这个返回结果. 如果直接返回的是值则没有任何意义, 因为返回的是值的时候返回的都是一个拷贝, 因此是可以随意修改的. 其实返回的是值可以看成这种

      const int cb = 10;
      int c = cb;
      c = 20;
            
      // 因为函数的声明可以看出变量的声明, 因此上下两个是等价的, 下面这样也是没问题的
      int a = 10;
      const int fun() {
        return a;
      }
      int c = fun();
      c = 20;

    2. 这个结论对在类里面的函数和对类外面的函数都试用

      #include <iostream>
      #include <stdio.h>
            
      class A {
       public:
        void set_rel(int val) {
          rel_ = val;
        }
            
        /*
         * 这里 relAddr1 和 relAddr 都是类似返回地址
         *
         * 这里 relAddr1 是c 里面的做法, 返回的是一个指针
         * 这个指针指向的是rel_ 的地址
         * 那么使用的时候就是
         * int *p = a->relAddr1();
         * *p = 30;
         * 那么这个时候a 里面的 rel_ 就会被修改
         *
         * relAddr 是c++ 里面的做法, 返回的是一个引用. 同样对返回的引用进行修改以后
         * 类里面的值也同样是有问题的
         *
         * 记住如果函数的返回类型是引用, 那么这个变量也必须是引用类型,
         * 才可以接到这个函数的引用
         * int &b = a->relAddr();
         * b = 30;
         * 那么这个时候a 里面的 rel_ 也同样被修改
         *
         */
            
            
        /*
         * 这里如果写成
         * const int *relAddr1() {
         *
         * 那么下面就不能用 int *p 对这个赋值
         * int *p = a->relAddr1(); // 也就是const 指针赋值给一个非const 指针的错误
         */
        int *relAddr1() {
          return &rel_;
        };
            
        /*
         * const int &relAddr() {
         * 这里如果给这个返回值加上const 以后, 那么下面的
         * int &b = a->relAddr();
         * b = 30; // 这里就是报错, 因为const 的意思是说这个返回值是无法修改的
         * 所以如果确实需要返回一个reference 的话, 也最好是返回一个const reference
         */
        int &relAddr() {
          return rel_;
        }
        const int rel() {
          return rel_;
        }
            
        int rel_;
      };
            
      /*
       * 这里const 对类外面的函数也同样适用, 所以如果需要返回的结果是& 或者* 的时候,
       * 最好对这个变量进行const 修饰, 表示不能给被修改
       */
      int ax = 10;
      const int& fun() {
        return ax;
      }
            
      int main()
      {
        A *a = new A();
            
        a->set_rel(10);
        printf("%d\n", a->rel());
            
        /*
         * 这里如果定义 const int &b, 那么接下来 b = 30 的时候就由于这个reference
         * 类型是const 所以不能赋值
         */
        int &b = a->relAddr();
        b = 30;
        printf("%d %d\n", b, a->rel());
            
        /*
         * 同样这里如果定义的是 const int *p, 那么接下来就不能操作*p = 40. 
         * 因为这个指针是const 类型的
         */
        int *p = a->relAddr1();
            
        *p = 40;
        printf("%d %d %d\n", *p, a->rel(), b);
            
        const int &xx = fun();
        // xx = 50;
            
        printf("%d %d\n", xx, ax);
              
        return 0;
      }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

创业无畏

创业无畏

彼得· 戴曼迪斯、史蒂芬· 科特勒 / 贾拥民 / 浙江人民出版社 / 2015-8 / 69.90元

 您是否有最大胆的商业梦想?您是否想把一个好主意快速转化为一家市值几百亿甚至几千亿元的公司?《创业无畏》不仅分享了成功创业家的真知灼见,更为我们绘制了一幅激情创业的行动路线图!  创业缺人手怎么办?如何解决钱的问题?把握指数型大众工具,互联网就是你车间,你的仓库。拥有好的创意,自然有人把钱“白白地送给你用”。当你大海捞针的时候,激励性大奖赛会让针自己跑到你的眼前来!  掌握指数级......一起来看看 《创业无畏》 这本书的介绍吧!

html转js在线工具
html转js在线工具

html转js在线工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具