详解const 用法

const关键字的基本功能和用法:

1.const的用法:

(1)定义常量

(2)修饰函数的参数

(3)修饰函数的返回值

(4)修饰函数的定义体

  1.将限定符声明为只读,修饰普通类型的变量。

       在类型前/后加上关键字const,该变量必须被初始化,否则编译错误;该变量不能被重新赋值,否则也编译错误。举例:    

const int i=100;  //ok
const int i;   //error
int k=0;
i=k;    //error i被定义为一个常量  不可以再对i进行赋值 其值不允许修改
k=i;      //ok   可以将i赋值给b,

 接着看下面代码:

int main()
{
    const  int a = 7;
    int *p = (int*)&a;
    *p=8;
    cout<<a;
    system("pause");
    return 0;
}

对于const变量a,我们取变量的地址并转换赋值给 指向int的指针,然后利用 *P=8;重新对变量a地址内的值进行赋值,然后查看a的值。从下面的窗口可得,a的值被修改为8,但是输出的结果仍然是7。

编译器一开始认为a的值为一开始定义的7,所以对const a 的操作进行出现如此情况。千万不要轻易对 const变量进行赋值 ,

如果不想让编译器察觉到对const的操作 可以加 volatile关键字   volatile关键字与const对应相反,是易变的,容易改变,所以不会被编译器优化,编译器也就不会改变对a变量的操作。

2.用于修饰函数的参数,保护参数使其不被修改

    (1)  const只能修饰输入参数

        如果输入参数采用“指针传递”,那么加const修饰可以防止意外地改动该指针所指向的对象的值。

       例如:void  StringCopy(char * strDestination,const char * strSource);

       若形参为 const A*a,则不能改变函数所传递的内容,这样对指针所指向的内容起到保护作用,这里需要注意的是,该修饰不能修饰指针所指向地址所存储的内容,但是指针a 所指向的地址可以被改变,

       若形参为 const A &a,则不能改变函数传递进来的引用对象,从而保护了原对象的属性。

        对于自定义的数据类型,用引用传递速度较快,如果不想改变原值,就可以用const来保护参数,如以下例子;

void Test(const int &a)  //保护 a  不会被改变
{
    a=2; //错误 a不能给常量赋值
}

(2)值传递的const修饰传递,一般情况不需要const修饰,因为函数会自动产生临时变量赋值实参值。

#include<iostream>
using namespace std;

void Cpf(const int a)
{
    cout<<a;
    //++a;     error  变量a 不能被改变
}

int main(void)
{
    Cpf(8);
    system("pause");
    return 0;
}

(3)而对于自定义数据类型(非内部数据类型)的输入参数,为了提高速度和效率,应使用“const + 引用传递” 代替值传递。

       例如:将void Test(A a)改为 void Test(const A &a)

         因为函数体内将产生A类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将耗费时间;“引用传递”只是借用一下参数的别名而已,不需要产生临时对象。

(4)事实上对于内置型数据类型的输入参数(如以上例子中的int类型),不要将“值传递”的方式改为“引用传递”,因为用引用传递不会使速度更快。即达不到提高效率的目的,又降低了函数的可理解性。

     例如: void Fun(int x) 改为  void Fun(const int &x)

    因为内部数据类型的参数不存在构造,析构的过程,而复制也比较快,“值传递”和“引用传递”的效率几乎相当。

3.用const修饰函数的返回值

   (1)如果给以 “指针传递” 的方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const修饰的同类型指针。

      例如:函数const char *GetString(void); 

        正确的是 :const char *str=GetString();     //写成 char *str=GetString(); 将出现编译错误

  (2)如果函数返回值采用“值传递”方式,由于函数会把返回值复制到临时的外部的存储单元上,所以加const没有任何价值。

      例如: 不要把函数 int  Getlnt(void) 写成 const int Getlnt(void).

    (3) 函数返回值采用“引用传递”的场合并不多,这种方式一般都只出现在类的赋值函数

4.const修饰指针变量

  const修饰指针变量有三种情况:

A: const修饰指针指向的内容,则内容为不可变量

const int *p =8;
//指针指向的内容8 不可改变,简称左定值,因为const位于 *号的左边

B:    const修饰的是指针,则指针为不可变量

int a =8;
int * const p=&a;
*p=9;         // ok   对于const指针p 其指向的内存地址不能够被改变,但是其内容可以改变,简称 右定向,因为const 位于*号的右边
int b=7;
p=&b;        //no

C: const修饰的是指针和指针指向的内容,则指针和指针指向的内容都是不可变量。

int a=8;
const int * const p=&a;
//const 不仅修饰指针p  还修饰p指向的内容,都已经固定,不可改变

对于A,B,C三种情况,根据const位于 *号位置不同,总结为:“左定值、右定向、const修饰不变量”

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值