C++_04_const用法 - 重写版

发布时间 2023-11-05 22:58:10作者: 尘落曦枫

const定义常量

  const是C++用来增加数据安全性,并且限制数据共享,保证数据不会被任意修改的机制。
  被const修饰的变量,其值在运行期间不能改变,即一经赋值不能再重新赋值,可以称为常变量
  切忌:定义任意类型的常变量必须同时对其进行初始化赋值,此后其值不能再改变(被赋值)

 

 

const修饰普通变量和指针 

  const修饰普通变量时要初始化赋值

#include<iostream>

using namespace std;

/*
    const修饰常量
    ---修饰成员变量时,必须在构造函数的参数列表中初始化
    ---修饰成员函数时,加在函数后面,并且该函数无法修改成员属性
*/
//const修饰普通变量时要初始化赋值
int main(int argc, char const *argv[]) { int x = 1; const int a = 10; int const b = 20; //定义两个整形常量,以上两种写法作用一致,没有区别(const和int谁前谁后无所谓) const int *c = &a; //const修饰指针指向的值为常整形, //指针的地址可以修改,但锁指向的数据不能修改 int * const d = &x; //const修饰的是指针本身,为常指针 //即指针变量(地址)不能修改,但是指针指向的数据可以修改 const int * const e = &a; //const同时修饰指针和指针指向的数据,两针皆不可修改
//前后主要看是在(*)前还是(*)后 cout << "-------------------初值---------------------" << endl; cout << "x = " << x << " " << "&x = " << &x << endl; cout << "a = " << a << " " << "&a = " << &a << endl; cout << "b = " << b << " " << "&b = " << &b << endl; cout << "c = " << c << " (a的地址)" << " *c = " << *c << endl; cout << "d = " << d << " (x的地址)" << " *d = " << *d << endl; cout << "e = " << e << " (a的地址)" << " *e = " << *e << endl; // a = 200; // b = 300; int m = 80; c = &m; /* *c = 400; */ // d = &m; *d = 500; // e = &m; /* *e = 600; */ cout << "-------------------赋值---------------------" << endl; cout << "x = " << x << " " << "&x = " << &x << endl; cout << "a = " << a << " " << "&a = " << &a << endl; cout << "b = " << b << " " << "&b = " << &b << endl; cout << "c = " << c << " (a的地址)" << " *c = " << *c << endl; cout << "d = " << d << " (x的地址)" << " *d = " << *d << endl; cout << "e = " << e << " (a的地址)" << " *e = " << *e << endl; return 0; }

 

 

const修饰成员变量

  在C++类中的成员变量,只能使用初始化参数列表进行初始化赋值
   成员变量的初始化顺序只与成员变量在类中声明的顺序有关
      例如:先有m_a,再有m_b,那么初始化时候,先赋值m_a后m_b

#include <iostream>
using namespace std;

class Demo{
    private:
        int a;
        char b;
    public:
        Demo(); //构造函数声明
    void show();
};

Demo::Demo():a(6),b('e') //构造函数定义,参数列表初始化 
{
} void Demo::show(){ cout<<a<<", "<<b<<endl; } int main(){ Demo obj; obj.show(); return 0; }

 

 

 

const修饰成员函数

  1、const成员函数可以访问const和非const成员变量,但是不能修改任何成员变量的值
  2、非const成员函数不能访问const成员变量,只能访问和修改非const成员变量
  3、const 成员函数是不能调用类中非 const 成员函数的。(const成员函数在只能调用const成员函数)

  const成员函数一般类中声明,类外定义,当然也可以类中声明定义

              

返回值类型 成员函数名(参数列表) const  
//注意:const修饰成员函数,放置函数名后面,函数声明和定义的时候都要加const {   函数体; }
//对于成员函数而言,const放在成员函数前,是限制函数返回类型为指针时通过指针对返回值的修改,
//非指针的函数返回类型前加const是没有意义的
//const放在成员函数后,是限制类的成员函数不能对成员变量进行修改

 

 

const修饰类对象

   在C++中const可以用来修饰对象,称为常对象。
    (const常对象只能调用const成员变量或成员函数)

语法格式:
const 类名 对象名(实参表列)  //方式1
类名 const 对象名(实参表列)  //方式2
const 类名 *指针名 = new 类名(实参表列); //指向常对象的指针法1
类名 const *指针名 = new 类名(实参表列); //指向常对象的指针法2
//以上同样是定义常对象的方法,对象不可变,指针可变
//以下是定义指向对象的长指针的方法,指针内存放不可变,对象可变
类名 *const 指针名 = 对象地址 //指向对象的常指针

上面的案例已经介绍过const修饰成员变量的场景了吗,这里就不再过多描述!!!

  const常对象只能调用const型成员变量或成员函数,不能调用非const型成员变量或成员函数;
    这是为了防止调用的成员变量或成员函数对常对象进行修改。

 

 

const常引用

格式;
const 类名 &引用名 = 对象名

  1、常引用只能调用常成员函数;
  2、常引用作为函数形参时,函数中不能有修改其对应实参的语句;
  3、常引用作为函数形参时,实参可以是一般对象、常对象、一般引用、常引用;
  4、一般引用作为函数形参时,实参只能是一般对象或一般引用。

 

 

const在C语言和C++中的比较:

  在C中const是“冒牌货”
    在C中  const int a = 10; 
           不是真的说a被定义为一个常量(冒牌货),a依旧可以通过指针修改其数据值
         C语言中const变量是只读变量,有自己的存储空间
    在C++中  const int a = 10; 
         const 定义的才是常量,不可修改。
         可能分配存储空间,也可能不分配存储空间
(C++中编译器将const修饰的变量放置在符号表中,在这个表中,不论是变量名、地址、数据本身都是不允许被改变的——就是完完全全的常量,当需要去地址的时候,会单独再分配一块空间,用指针存取(拷贝)变量的地址,这个地址对应的新空间数据和原来的数据没有一点点关系,不会影响到原来的数据值,如下图:)
         当const常量为全局,并且需要在其它文件中使用或者当使用&操作符取const常量的地址的时候,才分配内存空间,但也只是取地址,依旧不能修改内存中存放的2数据本身
         当使用&操作符,取const常量的地址时,会分配存储空间
         当const int &a = 10; const修饰引用时,也会分配存储空间

 

  正因为单独给const常量分配内存,导致有机会通过地址修改数据值,这样和常量初衷矛盾(C语言);
  正常情况下,C语言const会分配单独内存空间,但C++一般不会首先这样做。当C++需要分配内存空间的时候(编译过程中若发现对const使用了extern或者&操作符,则给对应的常量分配存储空间),也只能通过&获取地址,但不能更改存储空间的数据本身

 

 

const和#define比较

  const和#define相同之处
    C++中的const常量类似于宏定义         const int c = 5; ≈ #define c 5

  const和#define的区别之处
    const常量是由编译器处理的(编译期间),提供类型检查和作用域检查,const常量分配内存
    宏定义由预处理器处理(编译预处理期间),单纯的文本替换,故,宏定义不会重新分配内存

 

在c语言中
  1、const修饰全局变量num 变量名只读 内存空间在文字常量区(只读)、不能通过num的地址 修改空间内容
  2、const修饰局部变量data 变量名只读 内存空间栈区(可读可写),可以通过data地址 间接的修改空间内容

#include<stdio.h>
const int b =200;  //全局变量,存储在文字常量区
void main()
{
    const int a = 100;  //局部变量,存储在栈区
    printf("a = %d\n",a);
    printf("b = %d\n",b);
    //a = 2000;  //err
    //b = 2000;  //err
    printf("a1 = %d\n", a);
    printf("b1 = %d\n", b);
    int* pa = &a;
    *pa = 5000;  //局部变量
    int* pb = &b;
    //*pb = 5000;
    printf("a2 = %d\n", a);
    printf("b2 = %d\n", b);
}

 

C++中
  1、const修饰全局变量内存空间在文字常量区(只读)、不能通过num的地址 修改空间内容
  2、const修饰局部变量内存空间栈区(可读可写),可以通过data地址 间接的修改空间内容,但是修改的不是你想要改的数据,只不过被修改的是临时拉过来的群演,替身。

  1、const int data  = 10;//data先放入符号表
  2、如果对data取地址 系统才会给data开辟空间
  3、const int a  = b;//b是变量名 系统直接给a开辟空间 而不放入符号表
  4、cosnt 修饰自定义数据 系统为自定义数据开辟空间

#include<iostream>
using namespace std;

const int a = 200;

void main()
{
    cout << "全局变量a = "<<a << endl;
    //a = 2000;  //err
    //int* q = (int *)&a;
    //*q = 3000;
    cout << "全局变量a1 = " << a << endl;
    //cout << "全局变量a1 = " << *q << endl;

    const int b = 1000;
    cout << "局部变量b = " << b << endl;
    //b = 2000;
    int* p = (int *) & b;
    *p = 3000;
    cout << "局部变量b1 = " << b << endl;
    cout << "局部变量*p = " << *p << endl;

}