• const用法及与constexpr区别总结


    1、用const修饰函数的参数

    1. 参数是值传递

      由于函数将自动产生临时变量复制该参数,该参数无需保护,没必要用const

    2. 参数是指针传递或者引用传递

      const修饰的指针或引用所指向的值不可变。如果该参数只是起“被读取”的作用,最好用const修饰保护。

    对于复合数据类型,最好使用引用传递,因为值传递的过程中要进行临时对象的构造,复制,析构,这些都会造成时间和空间的浪费。

    class list {
        string name;
        public:
        	void show(const list& l) {
                cout << name;
            }
    }
    

    2、用const修饰函数的返回值

    如果函数的返回值用const修饰,接受这个返回值的变量也只能用const修饰。

    const int sum(int a, int b) {return a+b;}
    
    int s = sum(1,1); //error
    const s = sum(1,1); //编译通过
    

    3、const 成员函数

    任何不会修改数据成员的函数都应该声明为const 类型。如果在编写const 成员函数时,不慎修改了数据成员,或者调用了其它非const 成员函数,编译器将指出错误,这无疑会提高程序的健壮性。

    class list {
        string name;
        public:
        	void show(list& l) const {
                cout << name;
            }
    }
    

    4 、const对象

    const修饰的对象只能访问const函数和const成员变量

    class list {
        string name;
        public:
        	void show(list& l) const {
                cout << name;
            }
        	void show2(list& l) {
                cout << name;
            }
    }
    
    const list l;
    l.show2(); //error
    l.show(); //编译通过
    

    5 、与constexpr区别

    1. 对于修饰Object来说

      • const并未区分出编译期常量(编译时就可以确定的常量表达式)和运行期常量
      • constexpr限定在编译期常量,也就是说,编译器看见constexpr就可以放心的对常量进行编译期的优化了。
    2. 对于修饰函数来说

      • constexpr修饰的函数,返回值不一定是编译期常量

        #include <iostream>
        #include <array>
        using namespace std;
        
        constexpr int foo(int i)
        {
            return i + 5;
        }
        
        int main()
        {
            int i = 10;
            std::array<int, foo(5)> arr; // OK
            
            foo(i); // Call is Ok
            
            // But...
            std::array<int, foo(i)> arr1; // Error
           
        }
        

    所以,对于constexpr需要两方面看待。

    constexpr修饰的函数,简单的来说,如果其传入的参数可以在编译时期计算出来,那么这个函数就会产生编译时期的值。但是,传入的参数如果不能在编译时期计算出来,那么constexpr修饰的函数就和普通函数一样了。不过,我们不必因此而写两个版本,所以如果函数体适用于constexpr函数的条件,可以尽量加上constexpr

    而检测constexpr函数是否产生编译时期值的方法很简单,就是利用std::array需要编译期常值才能编译通过的小技巧。这样的话,即可检测你所写的函数是否真的产生编译期常值了。

    6、指向常量的指针(pointer to const)、常量指针指针(const pointer) 与 constexpr指针

    • 指向常量的指针,又叫底层指针

      • 作用:不能通过指针修改值,无论指向的值是否是const, 指针本身可以改变指向。

        int a =1;
        const int b = 1;
        const int* p;
        p = &a;
        *p = 2;//错误
        p = &b;
        *p = 2; //错误
        
    • 常量指针,又叫顶层指针

      • 作用:不能修改指针的指向,指针本身是常量,所以必须在声明时初始化。

        int a = 1;
        int b = 1;
        int* const p = &a;
        p = &b; //报错
        
    • constexpr指针

      • 作用和常量指针(顶层指针)一样

    6.5、类型别名与常量指针

    typedef int* ip;
    int a = 1;
    const ip p;  //等价于 int* const p;  也就是顶层指针,顶层指针必须初始化,所以这句是会报错的
    const ip p = &a; //正确
    

    7、const引用

    int const& a;const int& a; 作用一样,可以不加区分。

    参考:https://www.zhihu.com/question/35614219/answer/63798713

    https://www.jianshu.com/p/34a2a79ea947

    《C++ primer》2.4节

  • 相关阅读:
    Linux运维工作总结教训
    java-GC
    java设计模式-原形模式
    java-桥接模式
    java-装饰者模式
    java-正则表达式
    java设计模式-建造者模式
    Python 条件与循环
    Python 集合、字典、运算符
    Python 字符串拼接、格式化输出、深浅复制
  • 原文地址:https://www.cnblogs.com/rookiezjz/p/12347662.html
Copyright © 2020-2023  润新知