31 Oct 2016 本文阅读量

const关键字详解

const关键字的用法非常灵活, 使用const将大大改善程序的健壮性, const 允许指定一个语义约束,编译器会强制实施这个约束, 允许程序员告诉编译器某值是保持不变的, 如果在编程中确实有某个值保持不变,就应该明确使用const, 这样可以获得编译器的帮助。

定义常量

定义一个常量, 不允许对其进行修改。
同宏定义一样, 很方便地进行参数的调整,可以做到不变则已,一变都变

const int nMax = 100;

进行类型检查

const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误.

// 对传入的参数进行类型检查, 不匹配进行提示
void Function(const int nParam) {
}

保护被修饰的变量

防止意外的修改,增强程序的健壮性

//在函数体内修改了 nParam, 编译器会报错
void Function(const int nParam) { 
    nParam = 10; //error! 
}

为函数重载提供参考

class A {
  void Function(int nParam) {} //函数
  void Function(int nParam) const {} //重载函数
};

节省空间, 避免不必要的内存分配

const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是像 #define 一样给出的是立即数,所以const定义的常量在程序运行过程中只有一份拷贝,而 #define 定义的常量在内存中有若干个拷贝。

提高效率

编译器通常不为const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

指针使用const

  • 指针本身是常量
char* const pContent;
  • 指针所指内容是常量
const char *pContent;
  • 两者都为常量
const char* const pContent;

函数中的const

  • 参数指针所指内容为常量
void Function(const char* Var);
  • 参数为引用,增加效率同时防止修改。修饰引用参数时:
void Function(const int& Var); //引用参数在函数内不可变

这样的一个const引用传递和最普通的函数按值传递的效果是一模一样的,他禁止对引用的对象的一切修改,唯一不同的是按值传递会先建立一个对象的副本, 然后传递过去,而它直接传递地址,所以这种传递比按值传递更有效。

类中的const

  • const修饰成员变量 const修饰类的成员变量时不能被修改,同时它只能在初始化列表中赋值。
class A {
    const int nValue;    //成员常量不能被修改
    A(int x) : nValue(x) { } ; //只能在初始化列表中赋值
 };
  • const修饰成员函数 const修饰类的成员函数时不能修改类中任何非const成员函数
    一般写在函数的最后
class A {
   void Function() const; //常成员函数, 不能改变对象的成员变量,也不能调用类中任何非const成员函数。
};

对于const类对象/指针/引用,只能调用类的const成员函数,因此const修饰成员函数的最重要作用就是限制对于const对象的使用。

  • const成员函数不被允许修改它所在对象的任何一个数据成员。
  • const成员函数能够访问对象的const成员,而其他成员函数不可以。

const类型转化为非const类型

使用 const_cast 进行转换。
用法:const_cast (expression) 该运算符用来修改类型的const或volatile属性。

  • 常量指针被转化成非常量指针,并且仍然指向原来的对象;
  • 常量引用被转换成非常量引用,并且仍然指向原来的对象;
  • 常量对象被转换成非常量对象。

说在最后

  • 要大胆的使用const,这将给你带来无尽的益处,但前提是你必须搞清楚原委;
  • 在参数中使用const应该使用引用或指针,而不是一般的对象实例
  • 不要轻易的将函数的返回值类型定为const;
  • 除了重载运算符外一般不要将返回值类型定为对某个对象的const引用;
  • 任何不会修改数据成员的函数都应该声明为const 类型。

Tags:
Status:

Share:

Comments: