C/C++中const用法总结

C++中const修饰的变量、指针及函数一直弄得似懂非懂,经常受其困扰。趁有时间对其做以整理归纳。

const 变量、指针及成员对象

const修饰的变量称之为常量,定义时必须为其赋值,且后续不能修改其值。

const修饰的指针分为两种:指针常量(int *const p)和指向常量的指针(int const  *p 或 const int *p)。

const修饰的对象称之为常量成员对象,后续也不能修改其对象属性(内部私有变量),对于内置的数据类型,我们可以定义它们的常量,用户自定义的类也一样,可以定义它们的常量对象。

/*************const 常量***********/
int m = 10;
const int n = 20; // 必须在定义的同时初始化


/*************const 指针***********/
const int *ptr1 = &m; // 指针指向的内容不可改变,但指针可以重新指向其它地址
int * const ptr2 = &m; // 指针不可以指向其他的地方,但指针目前指向的地址中存放数据可以改变
 
ptr1 = &n; // 正确
ptr2 = &n; // 错误,ptr2不能指向其他地方
 
*ptr1 = 3; // 错误,ptr1不能改变指针内容
*ptr2 = 4; // 正确
 
int *ptr3 = &n; // 错误,常量地址只能赋值给常量指针
const int * ptr4 = &n; // 正确,常量地址初始化常量指针
 
int * const ptr5; // 错误,指针常量定义时必须初始化
ptr5 = &m; // 错误,指针常量不能在定义后赋值
 
const int * const ptr6 = &m; // 指向“常量”的指针常量,具有常量指针和指针常量的特点,指针内容不能改变,也不能指向其他地方,定义同时要进行初始化
*ptr6 = 5; // 错误,不能改变指针内容
ptr6 = &n; // 错误,不能指向其他地方
 
const int * ptr7; // 正确
ptr7 = &m; // 正确,指向常量的指针可以指向普通变量


/*************const 常量对象***********/
class A{
    public:
        A(int i){ car = 0; }
      int getCar() const;
      void setCar(const int);
        ......
    private:
        int car;
};
const A a = new A(6); // 对象a为常量对象

const修饰函数参数及返回值

在函数入参为一个class结构对象时,为了提高效率,往往需要进行引用传递(类似于C中的指针传递),这样会省去产生临时对象的构造、析构的过程,同时为了避免修改原始对象,常用const修饰该引用。

void Fun(A a); // 当调用Fun函数时,会创建临时对象a;在整个调用过程中会有构造、析构等过程,效率低下

void Fun(const A &a); //为了更高效的调用,传入对象引用。但为了保证原始对象不被修改,常用const修饰

如果希望函数的返回值为const类型的对象地址时,那么该函数返回值可定义为const修饰的类型指针,该返回值只能被赋给加const 修饰的同类型指针。

// 返回值为int类型的指针
const int* GetValue();

int *ptr = GetValue();   // 错误;
const int *ptr =  GetValue();   //正确;

如果返回值不是内部数据类型,返回值用对象的引用效率较高。但此时一定要小心,要搞清楚函数究竟是想返回一个对象的“拷贝”还是仅返回引用就可以了,否则程序会出错。

函数返回值采用“引用传递”的场合并不多,这种方式一般出现在类中对一些运算符的重载(重载=+,=,[ ] 等),结合另一篇博客中的string类实现:https://blog.csdn.net/ddazz0621/article/details/93981659

const修饰成员函数

我们定义的类的成员函数中,常常有一些成员函数不改变类的数据成员,也就是说,这些函数是"只读"函数,而有一些函数要修改类数据成员的值。如果把不改变数据成员的函数都加上 const关键字进行标识,显然,可提高程序的可读性。其实,它还能提高程序的可靠性,已定义成const 的成员函数,一旦企图修改数据成员的值,则编译器按错误处理

class A{
    public:
        A(int i){ car = 0; }
      int getCar() const;     //类的常量函数
      void setCar(const int);
        ......
    private:
        int car;
};

常量成员对象不能调用非常量成员函数,因为它可能企图修改常量对象的数据成员

构造函数和析构函数对这个规则例外,它们从不定义为常量成员,但可被常量对象调用(被自动调用)。它们也能给常量的数据成员赋值,除非数据成员本身是常量。

// 非常量成员对象调用
A objA = new A(6);

objA.getCar();    // 正确
objA.setCar(8);   // 正确

// 常量成员对象调用
const A objB = new A(6);

objB.getCar();    // 正确
objB.setCar(8);   // 错误;常量成员对象只能调用类的常量成员函数

以上为C++包含const修饰变量及函数的基本上所有的情况。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值