const,引用,const引用,非const引用

const

const的出现,把一个变量转换为一个常量,这样就避免了变量赋值在程序中由于过失而被改变,因为const是只读的。

1 定义const

因为常量在定义后不能被修改,所以const对象在定义时必须初始化。

    const std::string s = "welcome";//正确
    const int i;//错误

2 const对象默认为文件的局部变量

    //file_1
      int i ;
    //file_2
      extern int i; //使用file_1中的i
      i++;         //非const对象在file_2中仍然可以使用

除非特别说明,在全局作用域声明的const变量是定义该对象的文件的局部变量,不能被其他文件访问,只存在于定义它的文件中。
非const变量默认为extern。要使const变量能在其他文件中使用,必须显示地定义为extern const

    //file_1
    extern const int j = 3;
    //file_2
    extern const int j;//使用file_1中的j
    while(j!=5)
    {...}

引用

1 引用只是别名

引用只是它绑定的对象的别名,所有在作用在引用上的操作其实都是作用在该引用绑定的对象上。
引用必须用与该引用同类型的对象初始化,且必须定义时一并初始化

    int i = 3,j=5;
    int &k = i; //正确
    int &k; //错误
    int &k = 3; //错误
    int &m = i,&n = j;//定义多个引用
    int &m = i,n = j;//m是引用,n是int

const引用

const引用是指向const对象的引用

1 const引用的声明及初始化

1 能用同类型对象去初始化,且声明时初始化

    const int i = 1024;
    const int &j = i;//用同类型对象初始化
    int &m = i;//错误,m是非const引用,指向的值可修改,而i是const对象,不可修改,将普通的引用绑定到const对象是不合法的。

2 也能初始化为不同但相关类型*的对象或者右值(只有const引用能这样,非const引用依旧遵循只能用同类型对象去初始化)

    int i = 3;
    const int &j = 3;//合法
    const int &m = &i+j;//合法

绑定到不同类型时;

    double i = 3.14;
    const int &j = i;

编译器会把代码转换为如下形式的编码:

    int temp = i;
    const int &j = temp;//仅允许const引用绑定到需要临时变量作为媒介来完全绑定过程的值,因为const引用是只读的。

const形参

1 若函数形参为非引用非const,则既可以给该函数传递const实参也可以传递非const的实参。

    int rgcd(int a,int b)
    {...}
    const int i=3,j =6;
    int k = rgcd(3,6);//合法 

2 若形参定义为非引用的const类型,则在函数中不可改变实参的局部副本,但由于实参仍然是以副本的形式传递,所以既可以传递const实参,也可以传递非const实参

    int fcn(const int i)
    {...}

引用形参

引用形参和指针形参的出现,主要为解决复制实参的局限性
不宜复制实参的情况包括:

  • 当需要在函数中修改实参的值
  • 当需要以大型对象作为实参传递时。对实际应用而言,复制对象所付出的时间和存储空间代价往往过大
  • 当没有办法实现对象的复制时

指针形参

形参是指针形参的,传递对象时是复制指针实参。如果函数是将新的指针值赋给形参,主调函数使用的实参指针的值没有改变。

    void reset(int *ip)
    {
     *ip = 0;//使ip指向的对象值为0
     ip = 0;//仅改变ip在该函数中的值,实参并未改变
    }
    int i = 42;
    int *p = &i;
    cout<<"i:"<<*p<<'\n'; //i:42
    reset(p);
    cout<<"i:"<<*p<<endl;//i:0

如果要保护指针指向的值,则形参要定义为const对象的指针

    void use_ptr(const int *p)
    {
      //只能读取指针指向的值,而不能改变至指针指向的值
    }

既可以用int 也可以用const int 的实参来调用use_ptr函数,但仅能将int *类型的实参传递给reset函数。可以将指向const对象的指针初始化指向非const对象,但是不可以让指向非const对象的指针指向const对象

引用形参

与所有引用一样,引用形参直接关联到其所绑定的对象,而并非这些对象的副本。

  • 使用引用形参返回额外的信息
    比如解决函数有不止一个内容需要返回

  • 利用const引用避免复制
    如果使用引用的唯一目的是避免复制实参,则应将形参定义为const引用类型。

  • 更灵活的指向const的引用

         //函数形参为非const引用
         int incr(int &val)
         {
            return val++;
         }
         int main()
         {
            short v1 = 0const int v2 = 42int v3 = incr(v1);  //错误 v1不是int
            v3 = incr(v2);      //错误,v2是const
            v3 = incr(0);       //错误,0是常量,不是左值
            v3 = incr(v1+v2); //错误,加起来也不是左值
            int v4 = incr(v3); //正确,v3是int
         }

    应该将不需要修改的引用形参定义为const引用。普通的非const引用形参在使用时不太灵活,这样的形参既不能用const对象初始化,也不能用字面值实参或者产生右值的表达式的实参初始化。

  • 传递指向指针的引用
    通过实现两个指针的交换,实现交换两个整数的函数

        void ptrswap(int *&v1, int *&v2)  
        {
          int *temp = v2;
          v2 = v1;
          v1 = temp;
        }

    int *&v1 从右至左理解,只是传进ptrwasp 函数的任一指针的别名

           int main()
           {
              int i = 10;
              int j = 20;
              int *pi = &i ;
              int *pj = &j ;
              cout<<"Before ptrswap():\t *pi:"<< *pi<<"\t *pj:"<< *pj<<endl;
              ptrswap(pi,pj);
              cout<<"After ptrswap():\t *pi:"<< *pi<<"\t *pj:"<< *pj<<endl;
              return 0;
           }

    执行结果为:
    Before ptrswap(): *pi :10 *pj:20
    After ptrswap(): *pi :20 *pj:10
    即指针的值被调换了。之前pi指向i,pj指向j,现在pi指向j,pj指向i。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值