const限定符和constexpr初探

来源:互联网 发布:编程软件下载 编辑:程序博客网 时间:2024/05/29 14:41

const(常量)限定符

        const 定义的变量不能被改变,因此 const 对象必须初始化。

        对象的类型决定了其上的操作,const 对象只能执行不改变其内容的操作。例如用一个对象初始化另一个对象并不会改变本对象的值,只是进行了一次拷贝而已,一但拷贝完成,新的对象和原本的对象就毫无瓜葛了。

        默认情况下,const 对象仅在本文件内有效,当多个文件出现同名的 const 变量时,等同于在多个文件中分别定义了独立的变量。如果想要多个想要共享一个 const 对象时,我们不希望每个文件生成独立的变量,可以在 const 变量的声明和定义前添加extern 关键字。

const 和引用

        把引用绑定到 const 对象上(对常量的引用--reference to const),那么引用本身必须是 const 。

const int ci = 2015;const int &ri = ci;//引用及其对应的对象都是常量


 

       “对 const(常量)的引用”常被人简称为”常量引用“,事实上并不太正确,因为引用本身不是一个对象,如果时刻记得”常量引用“只是一个简称的话还是有些靠谱,毕竟C++语言本身并不允许随意改变引用所绑定的对象,所以这样理解的话所有的引用又都是常量~~好绕~~尴尬

       前面提到过引用必须与其所引用对象的类型一致,这里有第一个特殊情况,在初始化”常量引用“时,在该表达式的结果能转换成引用的类型的前提下,任何表达式都可作为初始值。

       对 const 的引用只是对引用本身可参与的操作做出了限定不能通过引用改变对象本身的值),并没有限定引用的对象本身是不是一个const(常量)。即“常量引用”可以绑定一个非常量。但是不能通过引用去修改对象的值,却可以通过其他途径来修改对象的值。

int i = 2015;int &r1 = i;const int &r2 = i;//r2可以绑定i,但是不允许修改它的值r1 = 2014;//正确,r1并非常量r2 = 2014;//错误,r2是一个对常量的引用(”常量引用“)


const 和指针

       同引用相同,指针也有指向常量的指针,即不能通过指针去修改其对象的值。

       指针本身是一个对象,所以存在货真价实的常量指针,即指针本身是一个常量。同任何常量对象一样,常量指针必须被初始化,一但初始化完毕它的值就不能再改变了。可以这样理解,常量指针是其本身的值(指针所指对象的地址)不能改变,而不是其所指对象的值不能改变。

int i = 2015;const int *p = &i;//p是指向常量的指针,不能通过p去修改i的值,但是i可以不是常量int * const cp = &i;//cp是常量指针,不能改变cp的值


        对于声明的理解有个好办法是从右向左读:

        对于 const int * p 来说,靠近p最近的是 * ,所以p是一个指针对象,对象的类型由声明符的其余部分决定,const 修饰的是其基本数据类型 int ,所以 p 是一个指向 int 常量的指针。

        对于int * const cp 来说,靠近 cp 最近的是 const ,说明 cp 本身是一个 const(常量)对象,对象的类型由声明符的其余部分决定,再往左看是一个 * ,即cp是一个常量指针,再往左看是其基本数据类型 int ,即 cp 是一个指向 int 类型的常量指针。

       

 

顶层 const 和底层 const

        顶层 const 表示任意的对象为常量,这些对象可以是算数类型,类,指针等等;而底层 const 则与指针和引用等复合类型的基本类型部分有关。

        指针既可以是顶层 const ,也可以是底层 const 。常量指针是顶层 const ,指向常量的指针是底层 const 。 

        在执行对象的拷贝操作时,顶层 const 不受影响,因为拷贝并不会改变对象本身的值(顶层 const 指对象本身为const)。但是底层 const 则必须要求拷入和拷出的对象具有相同的底层 const 资格,或者两个对象的数据类型能够转换,一般来说非常量可以转换为常量,反之则不行。

 

constexpr 和常量表达式

        常量表达式是指值不会改变并且在编译过程(运行后不算)就能得到值的表达式。在程序中会出现明明定义了常量表达式,但是却常常发现初始值并非常量表达式的情况疑问。所以C++允许将变量声明为 constexpr 类型来由编译器验证变量的值是否为常量表达式。一般来说如果认定变量时一个常量表达式,那就把它声明为constexpr类型。

        由于常量表达式的值需要在编译时就得到计算,因此声明 constexpr 的类型必须是及其简单的,计算值显而易见的类型,称为”字面值类型“。算数类型,指针,引用都属于字面值类型,可以被定义为 constexpr 。

        尽管指针和引用能被定义为 constexpr 类型,但他们的初始值受到严格的限定。一个 constexpr 指针的初始值必须是 nullptr 或者 0,或者是固定地址中的对象。(函数体中定义的对象不能是 constexpr )。

        如果用 constexpr 声明了一个指针,那这个 constexpr 只对指针有效。这与声明的传统读取方法有所出入。

constexpr int * q = nullptr;//q是一个指向整形的常量指针(顶层 const)


 

1 0
原创粉丝点击