• C++——const


    参考:https://www.cnblogs.com/Forever-Kenlen-Ja/p/3776991.html

     1.使用前必须初始化(编译时初始化,运行时初始化)

    2.extern const

    extern const int buffSize=255;//file1

    extern const int buffSize;//file2,包含file1,extern可以使得其被其他文件使用,避免多次定义

    const int  a = 7; //修饰变量,a不能该内容(更改为其他的值)
    int* const p = &a;//修饰指针,a可变,但p只能指向a,不能指向其他变量名
    const int *p = 8;//修饰指针指向的内容,不能改内容
    const int * const  p = &a;//既修饰指针,又修饰指针指向的内容:p不能指向别的变量,a的值也不能改
    
    void fun(const int a);//修饰传参,可要可不要const
    void fun(int *const a)//修饰传参指针,
    void fun(const int &a);//const+类型+引用传递(一般用于自定义类型),const 引用可以在保证参数不被修改的前提下,防止数据的值传递拷贝
    
    const int fun(){ return 1;}//修饰函数返回值
    const myType fun(){ return 1;}//修饰返回值,自定义类型,
    const int &fun(){ return i;}//修饰返回值的引用,//返回值不能是局部变量
    int *const fun(){ return &i;}//修饰返回值的指针,//返回值不能是局部变量
    
    
    int get() const  { return 1;}//修饰类成员函数,不能修改对象的数据成员而且不能调用非const函数

     void func(const A& a, int b, const int* c, int* d)const;//显然,上述成员函数中,a为const引用传递,不可以改变原值;b为值传递;c为const指针传递,不可改变原值;d为输出参数,可以改变原值。而该函数为const成员函数,不可以修改成员变量值。

    
    

     

    1.修饰变量,不对,修饰的是一个不可变的量

    const int  a = 7; 
    
    int  b = a; //it's right
     
    a = 8;       // it's wrong,

    取变量的地址并转换赋值给 指向int的指针,也改不了

        const int  a = 7;
    
        int  *p = (int*)&a;
    
        *p = 8;

    2.修饰指针

    A:const 修饰指针指向的内容,则内容为不可变量。

    const int *p = 8;

    B:const 修饰指针,则指针为不可变量。(p其指向的内存地址不能够被改变,但其内容可以改变。)

    int a = 8; 
    int* const p = &a;
    *p = 9; //it’s right
    int  b = 7;
    p = &b; //it’s wrong

    C:const 修饰指针和指针指向的内容,则指针和指针指向的内容都为不可变量。

    int a = 8;
    const int * const  p = &a;

     

    3.const参数传递

    A:值传递的const修饰传递(一般这种情况不需要const修饰,因为函数会自动产生临时变量复制实参值,实参值本身就是不可改变的)

    #include<iostream>
    using namespace std;
    
    void Cpf(const int a)
    {
        cout<<a;
        // ++a;  it's wrong, a can't be changed.
      // a=10; it's wrong, a can't be changed.
    
    }
    void Cpf1(int a)
    {
        cout<<a;
        // ++a;  it's wrong, a can't be changed.
      // a=10; it's wrong, a can't be changed.
    
    }
    int main(void) 
    {
     Cpf(8);
     Cpf1(9);
     system("pause"); 
    
    return 0; 
    }

    B:当const参数为指针时,可以防止指针被意外篡改。(但是指针指向的值可以改)(作用是什么呢?)

    #include<iostream>
    using namespace std;
    
    void Cpf(int *const a)
    {
        cout<<*a<<" ";
        *a = 9;
    }
    
    int main(void)
    {
        int a = 8;
        Cpf(&a);
        cout<<a; // a is 9
    
        system("pause");
        return 0;
    }

    C:const+自定义类型+引用传递

    对于一般的int ,double等内置类型,我们不采用引用的传递方式;

    自定义类型的参数传递,需要临时对象复制参数,对于临时对象的构造,需要调用构造函数,比较浪费时间,因此我们采取const外加引用传递的方法

    #include<iostream>
    using namespace std;
    
    class Test
    {
    public:
        Test(){}
        Test(int _m):_cm(_m){}
    
        int get_cm()
        {
           return _cm;
        }
    private:
        int _cm;
    }; 
    
    void Cmf(const Test& _tt)//const+自定义类型+引用传递
    {
        cout<<_tt.get_cm();
    }
    
    int main(void)
    {
        Test t(8);
        Cmf(t);
    
        system("pause");
        return 0;
    }

    4.const修饰函数的返回值

    归根究底就是使得函数调用表达式不能作为左值。

    A:const修饰内置类型的返回值,修饰与不修饰返回值作用一样。

    #include<iostream>
    using namespace std;
    
    const int Cmf()
    {
        return 1;
    }
    
    int Cpf()
    {
        return 0;
    }
    
    int main(void)
    {
    
        int _m = Cmf();
        int _n = Cpf(); 
    
        cout<<_m<<" "<<_n;
    
        system("pause");
        return 0;
    }
    #include <iostream>  
    using namespace std;  
      
    class A {
    private:
        int i;
    public:
        A(){i=0;}
        int & get(){
            return i;
        }
    };
     
    void main(){
        A a;
        cout<<a.get()<<endl; //数据成员值为0
        a.get()=1; //尝试修改a对象的数据成员为1,而且是用函数调用表达式作为左值。
        cout<<a.get()<<endl; //数据成员真的被改为1了,返回指针的情况也可以修改成员i的值,所以为了安全起见最好在返回值加上const,使得函数调用表达式不能作为左值
    }

    B:const 修饰自定义类型的作为返回值,此时返回的值不能作为左值使用,既不能被赋值,也不能被修改。

     

    C: const 修饰返回的指针或者引用,是否返回一个指向const的指针,取决于我们想让用户干什么。

     

    • 不能返回对局部对象的引用
    // Disaster: Function returns a reference to a local object
    const string &manip(const string& s)
    {
    string ret = s;
    // transform ret in some way
    return ret; // Wrong: Returning reference to a local object!//返回对局部对象的引用就会指向不确定的内存。
    }
    • 不能返回指向局部对象的指针
    • 当函数返回引用类型时,没有复制返回值。相反,返回的是对象本身

      例如,考虑下面的函数,此函数返回两个 string 类型形参中较短的那个字符串的引用:

    const string &shorterString(const string &s1, const string &s2)
    {
    return s1.size() < s2.size() ? s1 : s2;
    }

    5.const修饰类成员函数

    防止成员函数修改被调用对象的值。

    如果我们不想修改一个调用对象的值,所有的成员函数都应当声明为const成员函数。

    注意:const关键字不能与static关键字同时使用,因为static关键字修饰静态成员函数,静态成员函数不含有this指针,即不能实例化,const成员函数必须具体到某一实例。

    #include <iostream>
    using namespace std;
     
    class A{
    private:
        int i;
    public:
        void set(int n){ //set函数需要设置i的值,所以不能声明为const
            i = n;
        }
     
        int get() const{ //get函数返回i的值,不需要对i进行修改,则可以用const修饰。防止在函数体内对i进行修改。
            return i;
        }
    };

    在该函数体内,不能修改对象的数据成员而且不能调用非const函数。为什么不能调用非const函数?因为非const函数可能修改数据成员,const成员函数是不能修改数据成员的,所以在const成员函数内只能调用const函数。

     5.1 以下是const成员函数注意的几点

    
    

      1)const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数.即对于class A,有

    
    

      const A a;

    
    

      那么a只能访问A的const成员函数。而对于:

    
    

      A b;

    
    

      b可以访问任何成员函数。

    
    

      2)const对象的成员变量不可以修改。

    
    

      3)mutable修饰的成员变量,在任何情况下都可以修改。也就是说,const成员函数也可以修改mutable修饰的成员变量。c++很shit的地方就是mutable和friendly这样的特性,很乱。

    
    

      4)const成员函数可以访问const成员变量和非const成员变量,但不能修改任何变量。检查发生在编译时。

    
    

      5)非const成员函数可以访问非const对象的非const数据成员、const数据成员,但不可以访问const对象的任意数据成员。

    
    

      6)const成员函数只是用于非静态成员函数,不能用于静态成员函数。

    
    

      7)const成员函数的const修饰不仅在函数声明中要加(包括内联函数),在类外定义出也要加。

    
    

      8)作为一种良好的编程风格,在声明一个成员函数时,若该成员函数并不对数据成员进行修改操作,应尽可能将该成员函数声明为const 成员函数。

    6.const 引用

     

  • 相关阅读:
    java动态编译 (java在线执行代码后端实现原理)(二)
    java动态编译 (java在线执行代码后端实现原理)
    自己根据java的LinkedList源码编写的一个简单的LinkedList实现
    postman中 form-data、x-www-form-urlencoded、raw、binary的区别
    什么是Base64加密?为什么要有Base64加密?
    js获取上个月的第一天和最后一天
    js一个数组变为指定长度的多个数组
    java人民币转大写中文
    三天打鱼两天晒网
    一句便是一首【一】
  • 原文地址:https://www.cnblogs.com/yrm1160029237/p/10078698.html
Copyright © 2020-2023  润新知