C++知识点之const关键字

时间:2022-06-07 00:42:58

C++知识点之const关键字

1 const的用法

1.1 修饰变量

用于定义常量变量,这样这个变量在后面就不可以再被修改:

const int iValue = 10;
iValue = 20; //编译报错,iValue不可被修改

1.2 修饰函数入参

  1. 如果输入参数采用“指针传递”,那么加const 修饰可以防止意外地改动该指针。
    例如:void StringCopy(char *strDestination, const char *strSource);
  2. 如果输入参数采用“值传递”,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加const修饰。除非是想将该入参当作常量使用。
  3. 对于非内部数据类型的输入参数,应该将“值传递”的方式改为“const引用传递”,目的是提高效率。
    例如:将void Func(A a) 改为void Func(const A &a)
    因为函数体内将产生A类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将消耗时间;“引用传递”仅借用一下参数的别名而已,不需要产生临时对象。
  4. 对于内部数据类型的输入参数,不要将“值传递”的方式改为“const引用传递”(没意义)。否则既达不到提高效率的目的,又降低了函数的可理解性。
    例如:void Func(int x) 不应该改为void Func(const int &x)
    因为内部数据类型的参数不存在构造、析构的过程,而复制也非常快,“值传递”和“引用传递”的效率几乎相当。

1.3 修饰函数返回值

  1. 如果给以“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const修饰的同类型指针。
    例如:函数const char * GetString();
    正确的用法是: const char *str = GetString(); //写为char *str = GetString();将出现编译错误
  2. 如果函数返回值采用“值传递”方式,由于函数会把返回值复制到外部临时的存储单元中,加const修饰没有任何价值。
    例如:不要把函数int GetInt(void) 写成const int GetInt(void)。
  3. 函数返回值采用“引用传递”的场合并不多,这种方式一般只出现在类的赋值函数。

1.4 修饰成员函数

const 关键字放在函数声明的尾部。
例如:void func(const int* pInt) const {}
任何不会修改数据成员的函数都应该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其它非const 成员函数,编译器将指出错误,这无疑会提高程序的健壮性。

2 const的实现

const int i = 10;
//int *p = (int*)(&i); //c语言版本
int *p=const_cast<int *>(&i); //C++版本
*p = 20;

2.1 C与C++中const实现不同

C语言中const表示只读的变量,既然把const看成是变量,那么其在内存中就会有存储他的空间,并且可以通过指针间接的改变该内存空间的值,当通过指针p改变该内存中的值后,再获取i的值的时候,会访问该空间,得到的是被改变后的值。
C++把const看做常量,编译器会使用常数直接替换掉对i的引用,例如cout<<i; 会理解成cout<<10; 并不会去访问i的内存地址去取数据,这里有点像是C语言里的宏#define i 10。因此C++里i会输出10,而*p会输出20.

2.2 const修饰内置数据类型与非内置数据类型的区别

C++语言中const只是对于内置数据类型做常数替换,而对于像结构体这样的非内置数据类型则不会。因为结构体类型不是内置数据类型,编译器不知道如何直接替换,因此必须要访问内存去取数据,而访问内存去取数据必然会取到被指针改变后的值,因此会造成与C++中const int类型完全不一样的处理模式。