const

Posted chay

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了const相关的知识,希望对你有一定的参考价值。

面向过程设计中的const

定义常量

const修饰变量,以下两种定义形式:

TYPE const ValueName = value; 
const TYPE ValueName = value;

它的含义是:const修饰的类型为TYPE的变量value是不可变的。

指针使用const

const修饰指针,涉及到两个很重要的概念,顶层const和底层const
指针自身是一个对象,它的值为一个整数,表明指向对象的内存地址。进而,指针本身是否是常量以及所指向的对象是否是常量就是两个独立的问题。
顶层const(top-level const): 指针本身是个常量;
底层const(low-level const): 指针指向对象是一个常量;

  • 指针本身是常量不可变
 char* const pContent; 
  • 指针所指向的内容是常量不可变
 const char *pContent;
  • 两者都不可变
const char* const pContent; 

如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量。

函数中使用const

const 修饰函数参数

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

const 修饰函数返回值

const int fun1()

这个其实无意义,因为参数返回本身就是赋值。

const int * fun2()

调用时const int *pValue = fun2();

我们可以把fun2()看作成一个变量,即指针内容不可变。

int* const fun3()

调用时int * const pValue = fun2();

我们可以把fun2()看作成一个变量,即指针本身不可变。

一般情况下,函数的返回值为某个对象时,如果将其声明为const时,多用于操作符的重载。

类相关const

const修饰成员变量

const修饰类的成员函数,表示成员常量,不能被修改,同时它只能在初始化列表中赋值。

const修饰成员函数

const修饰类的成员函数,一般写在函数的最后来修饰。

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

const修饰类对象/对象指针/对象引用

  • const修饰类对象表示该对象为常量对象,其中的任何成员都不能被修改。对于对象指针和对象引用也是一样。
  • const修饰的对象,该对象的任何非const成员函数都不能被调用,因为任何非const成员函数会有修改成员变量的企图。
class A
 
    void func1(); 
    void func2() const; 
 
const A aObj; 
aObj.func1(); //错误
aObj.func2(); //正确
 
const A* aObj = new A(); 
aObj-> func1(); //错误
aObj-> func2(); //正确

将const类型转化为非const类型的方法

const_cast <type_id>  (expression) 
  • 常量指针被转化成非常量指针,并且仍然指向原来的对象;
  • 常量引用被转换成非常量引用,并且仍然指向原来的对象;
  • 常量对象被转换成非常量对象。

const 与 宏定义

  • const 与 宏定义一样,可以做到不变则已,一变都变。
  • const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误。
  • const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。
#define PI 3.14159         //常量宏
const doulbe  Pi=3.14159;  //此时并未将Pi放入ROM中
              ......
double i=Pi;   //此时为Pi分配内存,以后不再分配!
double I=PI;  //编译期间进行宏替换,分配内存
double j=Pi;  //没有内存分配
double J=PI;  //再进行宏替换,又一次分配内存!
  • 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

C++ 中const与C语言中const的区别

C++中,const变量默认是内连接的。也就是说它只能在定义它的文件内部使用,链接时其它编译单元看不见它。若要改为外部连接,则需要使用extern声明。

C语言中的const默认为外链接。

const  int bufsize  = 100;
char buf[bufsize]; 

在C++中正确,编译期间可以知道bufsize的值,在C语言中不正确,编译期间并不知道bufsize的值。

const int size;

这种定义形式在C语言中是正确的,因为它被C编译器看作一个声明,指明在别的地方分配存储空间。

但在C++中这样写是不正确的,必须写成:

extern const int size

或者:

const int bufsize = 100;  

内连接与外连接

编译是以源文件cpp文件为单位,编译成一个个的obj文件,然后再通过链接器把不同的obj文件链接起来。

内外链接的区别就在于:编译期间是否能够交互。

  • 内部连接:如果一个名称对于它的编译单元来说是局部的,并且在连接时不会与其它编译单元中的同样的名称相冲突,那么这个名称有内部连接。

  • 外部连接:在一个多文件程序中,如果一个名称在连接时可以和其它编译单元交互,那么这个名称就有外部连接。

以上是关于const的主要内容,如果未能解决你的问题,请参考以下文章

为啥在片段中从 char* 转换为 std::string 比转换为 const char* 更可取?

20个简洁的 JS 代码片段

inline内联函数

ECMAScript 2015:for 循环中的 const

JavaScript ES6 的let和const

神经网络:神秘的ReLu