zoukankan      html  css  js  c++  java
  • C++ const用法小结 (欢迎大家拍砖)

    C++ const用法小结 (欢迎大家拍砖)

     

    C++const 关键字小结

    const 是constant的缩写,本意是不变的,不易改变的意思。

    const 在C++中是用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数

    一、const修饰普通类型的变量。

    如下:

    1 const int  a = 7; 
    2 
    3 int  b = a; //it's right
    4 
    5 a = 8;       // it's wrong,

    a被定义为一个常量,并且可以将a赋值给b,但是不能给a再次赋值。对一个常量赋值是违法的事情,因为a被编译器认为是一个常量,其值不允许修改

    接着看如下的操作:

    复制代码
     1  
     2 
     3 #include<iostream>
     4 
     5 using namespace std;
     6 
     7 int main(void)
     8 
     9 {
    10 
    11     const int  a = 7;
    12 
    13     int  *p = (int*)&a;
    14 
    15     *p = 8;
    16 
    17     cout<<a;
    18 
    19     system("pause");
    20 
    21     return 0;
    22 
    23 }
    复制代码

    对于const变量a,我们取变量的地址并转换赋值给 指向int的指针,然后利用*p = 8;重新对变量a地址内的值赋值,然后输出查看a的值。

    从下面的调试窗口看到a的值被改变为8,但是输出的结果仍然是7。

     

    从结果中我们可以看到,编译器然后认为a的值为一开始定义的7,所以对const  a的操作就会产生上面的情况。所以千万不要轻易对const变量设法赋值,这会产生意想不到的行为。

    如果不想让编译器察觉到上面到对const的操作,我们可以在const前面加上volatile关键字

    Volatile关键字跟const对应相反,是易变的,容易改变的意思。所以不会被编译器优化,编译器也就不会改变对a变量的操作。

     

    复制代码
     1 #include<iostream>
     2 
     3 using namespace std;
     4 
     5 int main(void)
     6 
     7 {
     8 
     9     volatile const int  a = 7;
    10 
    11     int  *p = (int*)&a;
    12 
    13     *p = 8;
    14 
    15     cout<<a;
    16 
    17     system("pause");
    18 
    19     return 0;
    20 
    21 }
    复制代码

    输出结果如我们期望的是8

    二、const 修饰指针变量。

    const 修饰指针变量有以下三种情况。

     

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

    B:const 修饰指针,则指针为不可变量。

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

     

    对于A: 

      1 const int *p = 8; 

    //则指针指向的内容8不可改变。简称左定值,因为const位于*号的左边

     

    对于B:

    复制代码
    1  int a = 8;
    2  
    3  int* const p = &a;
    4 
    5  *p = 9; //it’s right
    6 
    7  int  b = 7;
    8 
    9  p = &b; //it’s wrong
    复制代码

    //对于const指针p其指向的内存地址不能够被改变,但其内容可以改变。简称,右定向。因为const位于*号的右边

     

    对于C:

    则是A和B的合并,

    1 int a = 8;
    2 
    3 const int * const  p = &a;
    4 
    5  

    //这时,const p的指向的内容和指向的内存地址都已固定,不可改变。

     

    对于A,B,C三种情况,根据const位于*号的位置不同,我总结三句话便于记忆的话,

    “左定值,右定向,const修饰不变量”

     

    三、const参数传递和函数返回值。

     

    对于const修饰函数参数可以分为三种情况。

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

    复制代码
     1 #include<iostream>
     2 
     3 using namespace std;
     4 
     5 void Cpf(const int a)
     6 
     7 {
     8 
     9     cout<<a;
    10 
    11     // ++a;  it's wrong, a can't is changed
    12 
    13 }
    14 
    15 int main(void)
    16 
    17 {
    18 
    19     Cpf(8);
    20 
    21     system("pause");
    22 
    23     return 0;
    24 
    25 }
    复制代码

     

    B:当const参数为指针时,可以防止指针被意外篡改。

    复制代码
     1 #include<iostream>
     2 
     3 using namespace std;
     4 
     5 void Cpf(int *const a)
     6 
     7 {
     8 
     9     cout<<*a<<" ";
    10 
    11     *a = 9;
    12 
    13 }
    14 
    15 int main(void)
    16 
    17 {
    18 
    19     int a = 8;
    20 
    21     Cpf(&a);
    22 
    23     cout<<a; // a is 9
    24 
    25     system("pause");
    26 
    27     return 0;
    28 
    29 }
    复制代码

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

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

    复制代码
     1 #include<iostream>
     2 
     3 using namespace std;
     4 
     5 class Test
     6 
     7 {
     8 
     9 public:
    10 
    11     Test(){}
    12 
    13     Test(int _m):_cm(_m){}
    14 
    15     int get_cm()const
    16 
    17     {
    18 
    19        return _cm;
    20 
    21     }
    22 
    23 private:
    24 
    25     int _cm;
    26 
    27 };
    28 
    29  
    30 
    31 void Cmf(const Test& _tt)
    32 
    33 {
    34 
    35     cout<<_tt.get_cm();
    36 
    37 }
    38 
    39 int main(void)
    40 
    41 {
    42 
    43     Test t(8);
    44 
    45     Cmf(t);
    46 
    47     system("pause");
    48 
    49     return 0;
    50 
    51 }
    复制代码

    //结果输出 8

     

    对于const修饰函数的返回值

    Const修饰返回值分三种情况。

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

    复制代码
     1 #include<iostream>
     2 
     3 using namespace std;
     4 
     5 const int Cmf()
     6 
     7 {
     8 
     9     return 1;
    10 
    11 }
    12 
    13 int Cpf()
    14 
    15 {
    16 
    17     return 0;
    18 
    19 }
    20 
    21 int main(void)
    22 
    23 {
    24 
    25     int _m = Cmf();
    26 
    27     int _n = Cpf();
    28 
    29  
    30 
    31     cout<<_m<<" "<<_n;
    32 
    33     system("pause");
    34 
    35     return 0;
    36 
    37 }
    复制代码

     

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

     

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

     

     

    四、const修饰类成员函数.

    const 修饰类成员函数,其目的是防止成员函数修改被调用对象的值,如果我们不想修改一个调用对象的值,所有的成员函数都应当声明为const成员函数。注意:const关键字不能与static关键字同时使用,因为static关键字修饰静态成员函数,静态成员函数不含有this指针,即不能实例化,const成员函数必须具体到某一实例。

     

    下面的get_cm()const;函数用到了const成员函数

     

    复制代码
     1 #include<iostream>
     2 
     3 using namespace std;
     4 
     5 class Test
     6 
     7 {
     8 
     9 public:
    10 
    11     Test(){}
    12 
    13     Test(int _m):_cm(_m){}
    14 
    15     int get_cm()const
    16 
    17     {
    18 
    19        return _cm;
    20 
    21     }
    22 
    23 private:
    24 
    25     int _cm;
    26 
    27 };
    28 
    29  
    30 
    31 void Cmf(const Test& _tt)
    32 
    33 {
    34 
    35     cout<<_tt.get_cm();
    36 
    37 }
    38 
    39 int main(void)
    40 
    41 {
    42 
    43     Test t(8);
    44 
    45     Cmf(t);
    46 
    47     system("pause");
    48 
    49     return 0;
    50 
    51 }
    复制代码

     

    如果get_cm()去掉const修饰,则Cmf传递的const _tt即使没有改变对象的值,编译器也认为函数会改变对象的值,所以我们尽量按照要求将所有的不需要改变对象内容的函数都作为const成员函数。

     

     如果有个成员函数想修改对象中的某一个成员怎么办?这时我们可以使用mutable关键字修饰这个成员,mutable的意思也是易变的,容易改变的意思,被mutable关键字修饰的成员可以处于不断变化中,如下面的例子。

     

    复制代码
     1 #include<iostream>
     2 using namespace std;
     3 class Test
     4 {
     5 public:
     6     Test(int _m,int _t):_cm(_m),_ct(_t){}
     7     void Kf()const
     8     {
     9         ++_cm; //it's wrong
    10         ++_ct; //it's right
    11     }
    12 private:
    13     int _cm;
    14     mutable int _ct;
    15 };
    16 
    17 int main(void)
    18 {
    19     Test t(8,7);
    20     return 0;
    21 }
    复制代码

    这里我们在Kf()const中通过++_ct;修改_ct的值,但是通过++_cm修改_cm则会报错。因为++_cm没有用mutable修饰

  • 相关阅读:
    外校培训前三节课知识集合纲要(我才不会告诉你我前两节只是单纯的忘了)
    floyd算法----牛栏
    bfs开始--马的遍历
    (DP 线性DP 递推) leetcode 64. Minimum Path Sum
    (DP 线性DP 递推) leetcode 63. Unique Paths II
    (DP 线性DP 递推) leetcode 62. Unique Paths
    (DP 背包) leetcode 198. House Robber
    (贪心 复习) leetcode 1007. Minimum Domino Rotations For Equal Row
    (贪心) leetcode 452. Minimum Number of Arrows to Burst Balloons
    (字符串 栈) leetcode 921. Minimum Add to Make Parentheses Valid
  • 原文地址:https://www.cnblogs.com/jack-hzm/p/8098204.html
Copyright © 2011-2022 走看看