作者:tongqingliu

转载请注明出处:http://www.cnblogs.com/liutongqing/p/7050815.html

C++之const限定符(顶层const,底层const)

const初始化

const的特点:

  • 用const加以限定的变量,无法改变。
  • 由于const对象定义之后就无法改变,所以必须对其进行初始化。
  • const对象的常量特征仅在尝试改变它的时候表现出来,其他时候和变量无异。

const初始化:

const int bufSize = 512; //bufSize无法再改变

const仅在本文件中有效

const对象通常只在本文件内有效,如果希望其在其他文件中也有效,则需要在其前面加上extern关键字。更详细的做法是,在一个文件中定义const,在其他多个文件中声明并使用它。

extern const int bufSize = 512;

顶层const和底层const

首先,const是一个限定符,被它修饰的变量的值不能改变。对于一般的变量来说,其实没有顶层const和底层const的区别,而只有对于指针这类复合类型的基本变量,才有这样的区别。

如何区分顶层const和底层const?

顶层const表示指针本身是个常量;

底层const表示指针所指向的对象是个常量。

指针如果添加const修饰符时有两种情况:

  • 指向常量的指针:代表不能改变其指向内容的指针。声明时const可以放在类型名前后都可,拿int类型来说,声明时:const int和int const 是等价的。声明指向常量的指针也就是底层const,下面举一个例子:
int num_a = 1;
int const *p_a = &num_a; //等价于const int *p_a = &num_a,指向const int 类型的指针,是底层const
//*p_a = 2; //错误,指向“常量”的指针不能改变所指的对象

注意:指向“常量”的指针不代表它所指向的内容一定是常量,只是代表不能通过解引用符(操作符*)来改变它所指向的内容。

上例中指针p_a指向的内容就不是常量,可以通过赋值语句:num_a=2; 来改变它所指向的内容。

  • 常量指针:代表指针本身是常量,声明时必须初始化,之后它存储的地址值就不能再改变。声明时const必须放在指针符号后面,即:const 。声明常量指针就是顶层const,下面举一个例子:
int num_b = 2;
int *const p_b = &num_b; //指向int类型的const指针,是顶层const
//p_b = &num_a; //错误,常量指针不能改变存储的地址值

其实顶层const和底层const很简单,一个指针本身添加const限定符就是顶层const,而指针所指的对象添加const限定符就是底层const。

区分顶层const和底层const的作用

为啥非要区分顶层const和底层const呢,根据C++primer的解释,区分后有两个作用。

1 执行对象拷贝时有限制,常量的底层const不能赋值给非常量的底层const。也就是说,你只要能正确区分顶层const和底层const,你就能避免这样的赋值错误。下面举一个例子:

int num_c = 3;
const int *p_c = &num_c; //指向const int的指针,是底层指针
//int *p_d = p_c; //错误,不能将底层const指针赋值给非顶层const指针
const int *p_d = p_c; //正确,都是指向const int的指针

2 使用命名的强制类型转换函数const_cast时,需要能够分辨底层const和顶层const,因为const_cast只能改变运算对象的底层const。下面举一个例子:

int num_e = 4;
const int *p_e = &num_e;
//*p_e = 5; //错误,不能改变底层const指针指向的内容
int *p_f = const_cast<int *>(p_e); //正确,const_cast可以改变运算对象的底层const。但是使用时一定要知道num_e不是const的类型。
*p_f = 5; //正确,非顶层const指针可以改变指向的内容
cout << num_e; //输出5

3练习

说了这么多,应该练习一下,const int constconst* pppi 是顶层const还是底层const?

答案当然是底层const,因为int前面const限定符,而最后一个*后面没有const限定符。看最后一个例子:

const int a = 1;  //a是顶层const
//int * pi = &a; //错误,&a是底层const,不能赋值给非底层const
const int * pi = &a; //正确,&a是底层const,可以赋值给底层const
const int *const *const ppi = &pi //即是底层const,也是顶层const
const int *const *const *pppi = &ppi; //底层const

指针和const限定符(另一版本理解方法)

  • 指向const对象的指针
  • const指针
  • 指向const对象的const指针
const double *p;// 指向const double类型的指针
double *const p = &pi; //指向double对象的const指针
const double *const p = &pi;//指向const对象的const指针

下面看几个例子:

指向const对象的指针

#include<iostream>
using namespace std;
int main()
{
double a = 1.2;
double *p = &a; //p是指向变量a的指针 const double pi = 3.14;
//p = &pi;//错,要想指向一个const对象,必须用指向const对象的指针
const double *cptr = &pi; //const double类型的指针
//*cptr = 1.5; //错,指向const对象的指针只能指向const对象,因而不能修改其值 system("pause");
}

const指针

指向const对象的const指针

#include<iostream>
using namespace std;
int main()
{
double a = 1.2;
double *p = &a; //p是指向变量a的指针 const double pi = 3.14;
//p = &pi;//错,要想指向一个const对象,必须用指向const对象的指针
const double *cptr = &pi;
cptr = &a; //指向const对象的指针也能指向非const对象
//*cptr = 1.5; //但是不能通过指针对其进行修改 int errNum = 0;
int *const curErr = &errNum; //指向int对象的const指针,必须进行初始化,而且该const指针不能再指向其他对象 const double *const pi_ptr = &pi; //指向const double对象的const指针
//不可以再指向其他的对象,而且也不可以通过指针修改对象的值 system("pause");
}

const写在左边也行,写在右边也行。

const string str1;
string const str2;

上面的两种写法都是对的。

参考:

C++ primer 第五版

http://blog.csdn.net/qq_19528953/article/details/50922303

C++之const限定符(顶层const,底层const)的更多相关文章

  1. C++ Primer 第二章 引用 指针 const限定符

    1.引用: 为对象起了另外一个名字,引用类型引用另外一种类型,通过将声明符写成&d的形式来定义引用类型,其中d也就是声明的变量名(声明符就是变量名). PS:1.通过图片中编译所提示的报错信息 ...

  2. C++之const限定符

    作者:tongqingliu 转载请注明出处: C++之const限定符 const初始化 const的特点: 用const加以限定的变量,无法改变. 由于const对象定义之后就无法改变,所以必须对 ...

  3. Spline样条函数 //C++关键字:operator // 重载函数 // 隐含的this指针 // 指针和const限定符

    在数学学科数值分析中,样条是一种特殊的函数,由多项式分段定义.样条插值是使用一种名为样条的特殊分段多项式进行插值的形式.由于样条插值可以使用低阶多项式样条实现较小的差值误差,这样就避免了使用高阶多项式 ...

  4. C++杂谈(一)const限定符与const指针

    const限定符 c++有了新的const关键字,用来定义常变量,可以替C语言中的#define.关于const限定符,有以下需要注意: 1.创建后值不再改变 2.作用范围在文件内有效 3.添加ext ...

  5. 变量和基本类型——复合类型,const限定符,处理类型

    一.复合类型 复合类型是指基于其他类型定义的类型.C++语言有几种复合类型,包括引用和指针. 1.引用 引用并非对象,它只是为一个已存在的对象所起的另外一个名字. 除了以下2种情况,其他所有引用的类型 ...

  6. C++中的常量(一) const限定符

    最近在重新看<<C++ Primer>>,第一遍的时候const和constexpr看得并不太懂,这次又有了些更新的理解,当然可能仍然有许多不对的地方... 首先,const限 ...

  7. [C/C++]const限定符总结

    const限定符 const是一种限定符,被const所限定的变量其值不可以被改变. const的初始化 由于const一旦创建其值就不能够被改变,所以我们必须对其进行初始化 const int a; ...

  8. 2变量与基本类型之const限定符

    一.const介绍: const对象一旦被创建其值就不能再改变,所以const对象必须初始化.任何试图对const赋值的行为都会引发错误. 二.初始化和const: 对const对象的主要限制就是只能 ...

  9. C++const限定符

    在C语言中我们使用#define宏定义的方式来处理符号常量.而在C++中有一种更好的处理符号常量的方法,那就是使用const关键字来修改变量声明和初始化.这种处理常量方式的好处不言而喻:如果程序在多处 ...

随机推荐

  1. centos7 二进制版本安装 mysql8.0.13

    一.下载mysql二进制安装包 mysql官网: https://dev.mysql.com/downloads/mysql/ 由于国内网络问题,个人建议使用国内开源镜像站下载: http://mir ...

  2. golang 实现延迟消息原理与方法

    实现延迟消息具体思路我是看的下面这篇文章 https://mp.weixin.qq.com/s/eDMV25YqCPYjxQG-dvqSqQ 实现延迟消息最主要的两个结构: 环形队列:通过golang ...

  3. golang语言中os包的学习与使用(文件,目录,进程的操作)

    os中一些常用函数的使用: package main; import ( "os" "fmt" "time" "strings&q ...

  4. 微软官方的.net开发人员代码示例

    微软官方的.net开发人员代码示例,需要的同学到这里下载: https://code.msdn.microsoft.com/

  5. 关于transform-style:preserve-3d的些许明了

    父元素要添加属性transform-style:preserve-3d;和transform:perspective(800px);还有相对定位 首先设置子元素 具有3D属性,然后再设置视角与3D元素 ...

  6. PAT 1076 Wifi密码(15)(代码)

    1076 Wifi密码(15 分) 下面是微博上流传的一张照片:"各位亲爱的同学们,鉴于大家有时需要使用 wifi,又怕耽误亲们的学习,现将 wifi 密码设置为下列数学题答案:A-1:B- ...

  7. (O)js核心:作用域链

    作用域 在一个函数被调用的时候,函数的作用域才会存在.此时,在函数还没有开始执行的时候,开始创建函数的作用域:   函数作用域的创建步骤: 1.函数形参的声明. 2.函数变量的声明. 3.普通变量的声 ...

  8. 简单使用limma做差异分析

    简单使用limma做差异分析 Posted: 五月 12, 2017  Under: Transcriptomics  By Kai  no Comments 首先需要说明的是,limma是一个非常全 ...

  9. JoyOI1035 棋盘覆盖

    原题链接 对棋盘染色,坐标和为奇数的染黑,偶数为白.这时会发现对于相同颜色的格子,是无法放置骨牌的,这样我们就将所有格子分成两类,然后根据能否放置骨牌连边,最后就是求二分图最大匹配了. 这里我是用的匈 ...

  10. a[i++]

    今天才知道,a[i++]到底是什么意思:: 其实也很简单了,就是a[i]的值还是a[i],然后i自增1: 把这篇博客当作平常各种错题博客吧,把各种从网上抄的代码不懂的地方写到这个地方算了 ====== ...