JiaHeng-DLUT
8/8/2019 - 11:21 AM

const

const

const 的使用

  1. constant

    const int MAX_N = 1e3;
    // = 
    // int const MAX_N = 1e3;
    // 含义:const 修饰的类型为 int 的变量 MAX_N 的值不可变
    
  2. pointer

    #include <iostream>
    using namespace std;
    
    int n1 = 1, n2 = 2;
    int* const p1 = &n1;     // 指针不可变,指向内容可以变
    const int* p2 = &n1;     // 指针可以变,指向内容不可变
    const int* const p3 = &n1;   // 指针不可变,指向内容不可变
    
    int main() {
     cout << "&n1:\t" << &n1 << "\t n1:\t" << n1 << endl;
     cout << " p1:\t" << p1 << "\t*p1:\t" << *p1 << endl;
     cout << " p2:\t" << p2 << "\t*p2:\t" << *p2 << endl;
     *p1 = 2;
     // p1 = &n2;
     cout << "&n1:\t" << &n1 << "\t n1:\t" << n1 << endl;
     cout << " p1:\t" << p1 << "\t*p1:\t" << *p1 << endl;
     cout << " p2:\t" << p2 << "\t*p2:\t" << *p2 << endl;
     // &n1:    004F4038         n1:    1
     //  p1:    004F4038        *p1:    1
     //  p2:    004F4038        *p2:    1
     // &n1:    004F4038         n1:    2
     //  p1:    004F4038        *p1:    2
     //  p2:    004F4038        *p2:    2
     return 0;
    }
    
    
    #include <iostream>
    using namespace std;
    
    int n1 = 1, n2 = 2;
    int* const p1 = &n1;     // 指针不可变,指向内容可以变
    const int* p2 = &n1;     // 指针可以变,指向内容不可变
    const int* const p3 = &n1;   // 指针不可变,指向内容不可变
    
    int main() {
     cout << "&n1:\t" << &n1 << "\t n1:\t" << n1 << endl;
     cout << " p1:\t" << p1 << "\t*p1:\t" << *p1 << endl;
     cout << " p2:\t" << p2 << "\t*p2:\t" << *p2 << endl;
     // *p2 = 2;
     p2 = &n2;
     cout << "&n1:\t" << &n1 << "\t n1:\t" << n1 << endl;
     cout << " p1:\t" << p1 << "\t*p1:\t" << *p1 << endl;
     cout << " p2:\t" << p2 << "\t*p2:\t" << *p2 << endl;
     // &n1:    008F4038         n1:    1
     //  p1:    008F4038        *p1:    1
     //  p2:    008F4038        *p2:    1
     // &n1:    008F4038         n1:    1
     //  p1:    008F4038        *p1:    1
     //  p2:    008F403C        *p2:    2
     return 0;
    }
    
    
  3. function

    // const 修饰函数参数
    
    // 传递过来的参数在函数内不可以改变(无意义,因为 Var 本身就是形参)
    void function(const int Var);
    
    // 参数指针所指内容为常量不可变
    void function(const char* Var);
    
    // 参数指针本身为常量不可变(也无意义,因为 char* Var 也是形参)
    void function(char* const Var);
    
    // 参数为引用,为了增加效率同时防止修改
    // 这样的 const 引用传递和最普通的函数按值传递的效果是一模一样的,禁止对引用的对象的一切修改
    // 唯一不同的是按值传递会先建立一个类对象的副本,,然后传递过去
    // 而它直接传递地址, 所以这种传递比按值传递更有效
    void function(const int& Var);   // 引用参数在函数内为常量不可变
    
  4. class

    #include<iostream>
    using namespace std;
    
    class Test {
    protected:
     int data;
    public:
     void fun1();
     void fun1() const;  // 上一函数的重载
     void fun2();
     void fun3() const;
    };
    
    void Test::fun1() {
     cout << "fun1() called " << endl;
    }
    
    void Test::fun1() const {    // const 是函数类型的一部分,实现部分也要带该关键字
     // data = 1;            // 常成员函数不能更新类的成员变量
     // fun2();              // 常成员函数不能调用该类中的非常成员函数,只能调用常成员函数。
     cout << "fun1() const called " << endl;
    }
    
    void Test::fun2() {
     cout << "fun2() called " << endl;
    }
    
    void Test::fun3() const {
     cout << "fun3() const called " << endl;
    }
    
    int main() {
     Test test1 = Test();
     const Test test2 = Test();
     
     test1.fun1();   // fun1() called
     test2.fun1();   // fun1() const called
    
     // 非常量对象也可以调用常成员函数,但是如果有重载的非常成员函数则会调用非常成员函数。
     test1.fun1();   // fun1() called
     test1.fun3();   // fun3() const called
     
     return 0;
    }
    
    

const 的作用

  1. 保护修饰内容

  2. 函数重载

  3. 类型检查

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

  4. 可以节省空间,避免不必要的内存分配

    // const 定义常量只给出了对应的内存地址
    // #define 给出的是立即数
    // 所以 const 定义的常量在程序运行过程中只有一份拷贝
    // 而 #define 定义的常量在内存中有若干个拷贝
    #define p1 3.14159           // 宏常量
    const double p2 = 3.14159;   // 此时并未分配内存
    double d1 = p1;              // 编译期间进行宏替换,分配内存
    double d1 = p2;              // 此时为 p2 分配内存,以后不再分配!
    double d1 = p1;              // 再进行宏替换,又一次分配内存!
    double d1 = p2;              // 没有内存分配
    
  5. 提高效率

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

const 的使用建议

  1. 任何不会修改数据成员的函数都应该声明为 const 类型;
  2. 在参数中使用 const 应该使用引用或指针,而不是一般的对象实例;
  3. 不要轻易的将函数的返回值类型定为 const
  4. 除了重载操作符外一般不要将返回值类型定为对某个对象的 const 引用。

References