c++: const 引用,const和指针

const和指针

指针是一种特殊的变量,它存储了一个内存地址。通过指针,我们可以直接访问和修改内存中的数据。而const关键字可以用来指定一个变量为常量,即其值不能被修改。

        当将const关键字与指针结合使用时,有两种常见的方式:

        1. 指向常量的指针:int const* a

  1.   a表示一个指向 常量 的指针,即指针指向对象的值不能通过该指针修改,但是该指针的指向(值)可以被修改。例如:
情况1:
int num = 10;
int const* a = #      // a 是指向常量的指针

num = 20;                 // 可以修改 num
// *a = 30;               // 错误,不能修改指针a指向的值

int num2 = 30;
a = &num2;                //可以修改指针的指向


//
情况2:
const int num3 = 40;      // num3 是常量,初始化后就不可修改
int const* a1 = &num3;    // a1 是指向常量的指针,

//num3 = 50;              // 不可以修改,num3为常量
//*a1 = 60;               // 错误,不能修改指针a1指向的值

   在上面的例子中a不能修改num的值,但是num的值可以通过别的方式修改,因此我们可以这么想: 所谓指向常量的指针(还有后面的引用),不过是指针(引用)"自以为是"罢了,他们觉得自己指向了常量,所以自觉地不去改变所指向对象的值。 然而指针(引用)所指向的值可能是常量也有可能是非常量。

       2. 常量指针:int* const a

        指针是对象,因此就像其他类型一样,允许把指针本身定为常量。  常量指针必须初始化,而且一定初始化完成,则他的值(也就是存放在指针中的地址)就不能再改变了。

       a表示一个 常量指针,这里的关键字位于 int *前面,说明指针是一个常量,则不能改变指针的值(也就是存放在指针中的地址)。 例如:

情况1:
int num = 10;
int* const a = #              // a是常量指针,a将一直指向&num

num = 20;                         // num不是const,可以修改num
*a = 30;                          // num不是const,可以通过*a修改num


int num2 = 30;
a = &num2;                        //错误,a是const指针,指针的值不能被修改


情况2:
const int num = 40;               //num 是常量,值不能改变
//int *const b = #            //错误,num是常量,num不能被改变,b是常量指针,可以改变指针a指向的值, 所以非法,

const int* const b1=#         //正确,a是指向常量的常量指针 

int num1 = 50;          
//b1=&num1;                       //错误,a是常量指针,不能改变它的值
//*b1 = 60;                       //错误,a是指向常量的指针,不能通过a改变a指向对象的值

        3. 顶层const和底层const

        顶层const说的是对象(整型、浮点型、字符型等等基本类型以及类和指针,但是不包括引用,因为引用不是对象)本身是const,   底层const说的是指针和引用的所指的对象是const。指针类型既可以是顶层const也可以是底层const。

        当执行对象拷贝操作时顶层const和底层const有区别:        

        执行拷贝操作时不会改变被拷贝对象的值,因此,对顶层const,考入和考出的对象是否是常量都没有什么影响。例如:

const int a=10;            //顶层const, a是常量
int b = a;                 //正确,对常量a没有影响
   
int c=20;
const int d =c;            //正确,d的初始值为20,不能再改变d了


   
int f = 0; 
int * e = &f;        

int *const h = e;          //正确,h是顶层const,h指向e,不能再改变h的指向了

int * g = h                //正确,h的指向没有改变

       但是底层const的限制不能忽略,当执行对象的拷贝操作时,考入和考出的对象必须具有相同的底层const资格,或者两个对象的数据类型能够转换。一般来说,非常量可以转换成常量,反之则不行。例如:

int A=5;
const int a =10;             
int *const b1 = &a;           //错误 a是常量,所以指向a的指针应该是指向常量的指针,这样才能保证a不改变,而b1是常量指针,不是指向常量的指针

const int* b2 =&A;            //正确, b2属于底层const 
int *const b3=&A;             //正确, b3属于顶层const

int* b4=b2;                   //错误, 不能将一个指向常量的指针赋值给一个指向非常量的指针

//我们要想清楚const到底是限制的什么? 我们执行拷贝操作的时候只要不改变const限制的对象的值就行。

int & c1=a;                   //错误, 不能将一个常量赋值给一个非常量的引用   
const int &c2 =a;             //正确,  c2是指向常量的引用,属于顶层const
&c2 =A;                       //正确, 非常量可以赋值给一个常量

int &c3=c2;                   //错误, 不能将一个指向常量的引用赋值给一个非常量引用


  

 const和引用

        可以把引用绑定到const上,像绑定其他对象上一样,我们称之为对常量的引用,与普通引用不同的是,常量的引用不能被用作修改它绑定的对象的值。例如:

const int a=10;
const int &A=a;         //A是常量的引用

A=10;                  //错误,不能修改A所绑定的值

        初始化:

        引用的类型必须与所引用对象的类型一致,在此条件下:对常量的引用初始化时允许用任意表达式作为初始值,只要该表达式的类型能转换成引用的类型即可,也允许绑定一个非常量的对象、字面值。 例如:

const int &A =40;        //允许用字面值作为初始值


int b =20;        
const int &B =b;        //正确,常量的引用 可以绑定一个非常量对象
B=30;                   //错误,不能修改B所绑定的值


const int &C = b*2;     //正确,可以用表达式结果作为初始值

///

const int &D =20; 
int &E = D;             //错误,不能将常量引用赋值给一个非常量引用


const double f=20.1;
const int &H=f;         //错误,引用的类型必须与所引用对象的类型一致

                   

你可能感兴趣的:(c++,开发语言)