前沿

        前面吐槽下, 我发现很多人都是不看c++标准的,就这个const使用,标准里面明明说了,把被修饰的东西放在const左边,但是你搜文章一大堆放在右边的,说是好看,最后c++那边也兼容了放在右边这种写法。

口诀

const默认作用于其左边的东西,如果左边没有东西那么作用于其右边的东西

        我们在用的是,先从右到左(其实就是从后往前)找const关键字,按照口诀就能找到const修饰的东西了

对我说的前沿做解释

        下面这段代码是正确的

int main (){
    const int a = 10;
    const int* const p=&a;
    cout << p << a << *p << endl;
    return 0;
}

        但是你把第三行改一下,变成下面这样,这就会编译出错,为什么呢,因为这种写法按我们的口诀了你会发现第一个const找不到修饰的东西,本来你可能想 ,哦 const intconst * 那不就是一个指向常量的常量指针嘛,然而事与愿违

int main (){
    const int a = 10;
    // 这儿做了修改
    const int const* p=&a;
    
    cout << p << a << *p << endl;
    return 0;
}

        按c++最标准的写法应该是这样的,这就是我为什么说他们使用错误

int main (){
    int const a = 10;
    int const * const p=&a;
    
    cout << p << a << *p << endl;
    return 0;
}

说几种没啥用,但是面试官又会问你的使用

const函数返回值

const int fun( int i);

// 更合标准的写法
int const fun( int i);

        没啥用,按我们的口诀,那的含义就是fun函数的返回值是一个常量,然而,因为返回值是值传递的,所以如果返回的就是一个值的话,没有任何意思。例如:

int main (){
    int const a = 10;

    int const * const p=&a;
    int const fun( int i);   // 加不加const 没啥区别
    // p = &a;
    cout << p << a << *p <<fun(0)<< endl;
    return 0;
}
int const fun( int i){    
    int a=10;
    return a+1;
}

        当然如果返回值是一个指针的话,还是有用处的,表示指针指向的对象不能修改,指针是只读指针,不能通过指针向地址写入值

const int* fun();
//你们知道我要写啥
int const * fun();

const函数参数(指针,引用类)

void fun(const int * i);
void fun(const int & i);

//同样,更标准的写法
void fun(int const * i);
void fun(int const & i);

        不能在函数体内修改指针或引用指向的值,但是这里指针可以转而指向其他值(其实没多大用,因为指针本身就是值传递,即使改变指向,也不会影响实参的指向,除非用二级指针)

补一点点东西

const 不能修饰引用

        会编译报错。 引用不能是 const 指定的,因为不存在可变引用。

int main (){
    int const a = 10;
    int const & const p=a;
    return 0;
}
const int* const& const p;  //这个也是错的,但是群里有人说能编译通过在 msvc 上 :

const 写在函数后面,则表示这个函数不修改类的非静态成员变量,

        注意 如果是静态成员变量,还是会被修改的,如下示例

#include <cstdlib>
#include <iostream>

using namespace std;

struct A {
    static int s;
    int a = 2020;

    void increase() // 对非静态成员变量进行了修改,不能声明为 const
    {
        a++;
    }

    void print() const // 语义上对内部成员没有修改的函数,建议声明为 const
    {
        cout << a << ' ' << ++A::s << endl;
    }
};

int A::s = 0;

int main(int argc, char *argv[])
{
    A a;
    a.increase();
    a.print();
    return 0;
}

const的好处

  1. 可以节省空间,避免不必要的内存分配。(相对于宏定义)

        const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。

  1. 效率更高

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

  1. 更安全

        const常量具有数据类型, 而宏常量没有数据类型. 编译器可以对前者进行类型安全检查, 而对后者只会进行字符替换, 没有类型安全检查, 容易发生意想不到的错误.