C++ const 关键字总结

    添加时间:2013-7-26 点击量:

    C++ 中关于 const 的常识点很多,在这里做个总结。


    const 关键字润饰的变量在创建后值就不克不及改变了,是以必须在创建时进行初始化。


    对象的类型决意了可以或许在对象长进行哪些操纵。对 const 对象来说,只能应用那些不克不及改变对象状况的操纵。


    若是 const 对象是由一个编译时常量(compile-time constant)进行初始化的:



    const int bufSize = 512; // input buffer size 


    那么编译器一般会在编译时用这个常量调换该 const 变量。即编译器把所有效到 bufSize 的处所调换为512。为了进行这种调换,显然编译器须要知道 const 变量的初值是几许,这就须要搜检 const 变量是如何被定义并初始化的。


    若是法度分布在多个文件中,为了对变量的值进行调换,编译器在编译每个用到该 const 变量的文件时,都须要知道该 const 变量是如何被定义的,这就请求在每个用到该 const 变量的文件中都对该变量进行定义(define 而不是 declare),然而一个变量是不克不及被多次定义的。为解决这个抵触,规定 const 变量的感化域是文件本身(local to file)。在多个文件中定义名字雷同的多个 const 变量时,就像在每个文件中定义了一个不合的变量一样。


    (对于一般变量来说只能在一处进行定义,在其他文件中应用时须要应用 extern 关键字进行声明。)


    有时我们想在多个文件享一个 const 变量,然则该 const 变量的初始化器(initializer)并不是一个常量表达式(constant expression,常量表达式的值在编译时就可以被断定,如一个数字或算术表达式,一个经由过程 constant expression 进行初始化的 const 变量也是一个 constant expression)。在这种景象下,我们不编译器在每个用到该 const 变量的文件中都零丁生成一个新的变量。我们在一个文件中进行定义,在其他文件中进行声明。要达到这一目标,须要在定义和声明时同时应用 extern 关键字(不然就是 local to file)。



    // file_1.cc 
    extern const int bufSize = fcn(); 
     // file_1.h 
    extern const int bufSize; 


    下面用代码具体演示一下。若是是 nonconst 的变量,则只能在一处进行定义。



    // file_1.cc 
    #include <cstdio> 
    int bufSize = 512; 
    void print(); 
    int main() { print(); return 0; } 
    // file_2.cc 
    #include <cstdio> 
    int bufSize = 100; 
    int print() { printf\n%d\n bufSize); return 0; } 


    编译时报错:multiple definition of bufSize。若是将两个 bufSize 中的一个改为 const,或两个都改为 const,则编译经由过程,输出 100。



    // file_1.cc 
    #include <cstdio> 
    const int bufSize = 512; 
    void print(); 
    int main() { print(); return 0; } 
    // file_2.cc 
    #include <cstdio> 
    extern const int bufSize; 
    int print() { printf\n%d\n bufSize); return 0; } 


    若是是如许,file_1 中进行定义时没有加 extern 关键字,则编译时报错:undefined reference to bufSize


    若是将两个文件中的 const 关键字都去掉,或者给 file_1 中的 const 变量也加上 extern 关键字,编译成功,输出512。


    对 const 变量的引用


    像通俗变量一样,也可以将一个引用绑定到一个 const 变量。对 const 变量的引用同样不克不及改变该 const 变量的值。



    const int ci = 1024; 
    const int &r1 = ci; r1 = 42; // 错误,不克不及经由过程对 const 的引用改变 const 变量的值 
    int &r2 = ci; // 错误,不克不及用 nonconst reference 引用 const 变量 


    指针,const 和类型别号(type aliases)


    推敲下面的代码:



    typedef char pstring; const pstring cstr = 0; const pstring ps; 


    const 润饰的是 pstring,而 pstring 的类型是指向 char 的指针,所以 const pstring 是一个 constant pointer to char,而非 pointer to const char。


    不克不及经由过程直接调换来懂得类型别号:



    const char cstr = 0; // 这是对 const pstring cstr 的错误懂得 


    const 参数


    进行赋值时,top-level const 会被忽视,所以以下两个函数定义不克不及同时存在:



    void fcnconst int i {} 
    void fcnint i {} 


    这两个函数可以或许接管同样的参数,所以不算重载。


    可以用 nonconst 对象对 low-level const 对象进行初始化,但不克不及用 low-level const 对象初始化 nonconst 对象。(low-level const 指针认为其指向的对象是 const 对象)。



    int i = 42; 
    const int cp = &i; // ok: cp 是 low-level const,可以用 nonconst 进行初始化,但不克不及经由过程 cp 改变 i 的值 
    const int &r = i; // ok: reference to const,不克不及经由过程 r 改变 i 的值 
    const int &r2 = 42; // ok 
    int p = cp; // error: 不克不及用 low-level const 初始化 nonconst,但可以用 const_cast 强迫转换 
    int &r3 = r; // error 
    int &r4 = 42; // error: 不克不及经由过程 literal 初始化 plain 的 reference 


    若是可能就应当应用 reference to const


    不消 reference to const,会让调用者错误地认为函数会改变参数的值。并且不消 reference to const,会限制可以或许传递的参数类型。不克不及向通俗的 reference 传递 const 对象,不克不及传递 literal,不克不及传递须要转换的类型。


    const 成员函数


    成员函数的参数列表后面可以加关键字 const,感化是润饰 this 指针。


    this 指针默认是 const pointer to nonconst object,故不克不及指向 const object,也就是说 const 对象的办法无法被调用。将成员函数变为 const 成员函数,其 this 指针隐含参数变为 const pointer to const object。const 成员函数不克不及改变对象状况。const 对象只能调用 const 成员函数。


    重视 const 成员函数若是返回 this,那么返回的是一个 const 对象,不克不及在返回对象根蒂根基上持续调用 nonconst 的成员函数。为解决这一点可以基于成员函数的 constness 对成员函数进行重载。


    真正的心灵世界会告诉你根本看不见的东西,这东西需要你付出思想和灵魂的劳动去获取,然后它会照亮你的生命,永远照亮你的生命。——王安忆《小说家的十三堂课》
    分享到: