什么是const限定符?

Const限定符是我们通常所说的常量限定符,被const修饰的对象具有常量性质,只能读,不能写。

为什么使用const限定符?

用const变量取代“魔数”,代码更容易理解和维护。例如:以const常变量作为数组的界;const常变量作为switch的条件标号。

C++“最小特权原则”的体现,防止不应该被修改的数据被篡改。例如:很多指针(或迭代器)是边读边移动,而不是边写边移动;很多函数参数是只读不写的,使用const限定符不仅可以限制参数被修改,还可以扩大函数可以接受参数的范围(可以接受const对象作为参数)。

如何使用const限定符?

1、 变量:const 类型 变量名  例如: const int ia = 5;

2、 引用:const 类型 &引用名 例如:const int &ib = ia;

3、 对象:const 类名 对象名

4、 指针:const 类型 * 指针名 (常量指针); 类型 * const 指针名 (指针常量)

5、 数组: const 类型 数组名[Arr_Max]

6、 成员函数: 类名::函数名(形参表) const

PS: 上述几种情况中,除 指针常量 和 const修饰成员函数外,其他几种情况的 const  和 类型或者类名(类是一种自定义的类型)的位置可以互换, 比如: const int ia = 5; 与 int const ia = 5; 等同。 建议坚持使用一种风格。

const 限定符几种用法详解:

1、 指针

使用指针时涉及到两个对象:该指针本身和指针指向的对象。根据这两个对象是否使用const修饰,将会产生以下四种情况:

指向非常量对象的非常量指针 int *ptr;

指向非常量对象的常量指针   int *const ptr1;

指向常量对象的非常量指针   const int *ptr2;

指向常量对象的常量指针     int const *const ptr3;

从右向左解读声明:

Ptr1 is a const pointer to int.       ptr1 是一个const指针,指向int对象。

Ptr2 is a pointer to const int.   ptr2是一个指针,指向const int 对象。

Ptr3 is a const pointer to const int.   ptr3是一个const指针,指向const int 对象。

如果指针本身被修饰为常量,则该指针在定义时就应该初始化,且之后都不能变更指向的对象(即不能给指针赋值),但是可以通过解引用修改指向对象的值。

例如:

int i = 10, j = 20;

int *const ia = &i;  // 定义时必须初始化

*ia = 100;   //正确,可以修改指向变量的值

ia = &j;    //错误,不允许给const修饰的指针赋值

ia = &i;     //错误,不允许给const修饰的指针赋值(即使是赋同样的值)

如果指针指向的对象被修饰为常量,则不能在对指针进行解引用之后修改对象的值,但可以变更指向的对象。

例如:

int i = 10, j = 20;

const int *ia = &i;

*ia = 100;  // 错误,不允许通过指针修改指向对象的值

ia = &j;     // 正确, 指针本身未被const修饰,可以变更指向对象

PS: 试图通过ia 修改指向变量的值是不被允许的,但并不是说明变量的值不能被修改,我们依然可以通过其他方式修改变量的值,比如直接赋值i = 100。变量的值能不能修改取决于该变量本身。 const修饰指针指向的变量,只代表从该指针的角度来看,这个变量具有const特性,不能通过该指针来修改。也完全可能通过另一个指针来修改,比如: int *ib = &i; *ib = 100 ;

如果指针指向的对象本身具体const特性,则被指向对象的值不允许被修改,包括直接修改或者间接修改(通过指针或者引用修改)。 因此,C++语言强制要求指向const对象的指针也必须具有const特性,否则会出现编译错误(C++ primer 中文第四版)。 这意味着,只有指向常量对象的指针才能指向一个const变量。

例如:

const int i = 10;

int *ia = &i ;    //编译错误

const int *ib = &i;  //正确

int *const ic = &i;  //编译错误

const int *const id = &i; //正确

2、 引用

一个变量的引用即一个变量的别名,引用本身不能再次赋值让一个引用成为另一个变量的别名。因此,相对于指针,const在修饰引用变量的时候就只需考虑能否通过引用变量来修改绑定变量的值。即只存在两种引用:const变量的引用 和 非const变量的引用。在其他特性方面,引用和指针一致。

例如:

int i = 10;

const int j = 20;

const int &ra = i;  //正确, 表示不能通过ra去修改i的值

int &rb = j;  //编译错误,只有const变量的引用才能与const对象绑定

const int &rc = j;  //正确

int &const rc = i;  //语法错误,不同于指针,引用不能这样定义

PS:在程序加载的时候,系统将内存划分为5个区域:堆区、栈区、全局区(静态区)、文字常量区和程序代码区。对于const修饰的变量,系统没有划定专门的区域来保护其中的数据不被修改。也就是说,使用常变量的方式对数据进行保护是通过编译器作语法限制来实现的。我们依然可以绕过编译器的限制去修改被const限定为“常量”的区域。例如:C语音中通过指针间接修改const变量的值,C++中借助volatile关键字修改const变量的值。 但是C++标准中,对于修改const变量属于”未定义行为”,其实际结果取决于各种编译器的实现。因此,不建议修改去const变量的值(这不废话嘛,如果要修改,定义为const干什么)。

3、 形参

const限定符修饰形参,本质上也是修饰各种变量。在调用函数的时候,实参到形参采用的是值传递。

对于非引用形参,无论是否有const修饰,都可以给函数传递const实参或者非const实参,实际传递的都是实参的一个副本。区别仅在于形参在函数内部使用的时候需要遵循相应的变量读写规则。特别是,尽管函数的形参定义为const,但编译器也将其视为普通的类型。

例如同时定义函数 int Fib(int n)  和int Fib(const int n),编译器将会报错:error C2084:函数“int Fib(int)”已有主体。

这种用法是为了支持对C语言的向下兼容,因为在C语音中,具有const形参或非const形参的函数并无区别(C++ primer 中文第四版)。

复制实参具有一定的局限性,并不是在所有的情况下都适用,不适用的情况包括但不限于:需要在函数值修改实参的值; 复制大型对象所付出的时间和空间代价过大; 对象无法实现复制。针对上述情况应该将形参定义为引用或者指针类型。

对于引用形参,如果函数具有非const引用形参,则不能通过const对象调用函数。毕竟,此时函数可以修改传递进来的对象,这样就违背了实参的const特性。如果函数不会去修改实参的值,则应该将相应的形参定义为const引用,这样形参才能接受const实参,否则会毫无必要的限制该函数的使用。

4、 成员函数

const限定符可以修饰类的成员函数,一般放在函数体后,形如:int fun() const;

   const实际修饰了成员函数隐含的this指针形参,使this指向的对象本身具有const性质。因此,const成员函数将无法修改数据成员(mutable修饰的数据成员除外),也无法调用其他非const成员函数。任何不会修改数据成员的成员函数都应该声明为const类型,这样在不慎修改到数据成员或者调用到非const成员函数时编译器将会报错。

5、函数返回值

  如果函数返回的是一个左值(如引用类型、指针类型),那么该返回值可以被const修饰。形如:

 const string& shortString(const string &str1, const string &str2)
{
return str1.size() < str2.size() ? str1 : str2;
}

  其返回的变量是const string& 类型,因此函数的返回值也必须具有const性质。

  

浅谈const限定符的更多相关文章

  1. 简谈const限定符

    const修饰的数据类型是常量类型,常量类型的对象和变量在定义初始化后是不能被更新的.其实只用记住这一个概念,就可以明白const操作对象的方法. 1)定义const常量 最简单的: const in ...

  2. C++const限定符

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

  3. const 限定符

    1.定义const对象 const限定符把一个对象转换成一个常量 const int Bufsize = 512; 定义Bufsize 为常量并初始化为512.变量Bufsize仍然是一个左值,但是不 ...

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

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

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

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

  6. 指针和Const限定符

    指针和Const限定符 1.指向const对象的指针 如果指针指向的是const对象,则不允许使用指针来改变其所指的const值.C++要求指向const对象的指针具有const特性. const d ...

  7. C++ const 限定符

    C++ const 限定符 作用:把一个对象转换成一个常量 用法:const type name = value; 性质:1. 定义时必须初始化,定义后不能被修改.2. 类中的const成员变量必须通 ...

  8. const限定符的作用

    const限定符的作用:                                     1.定义const常量:const可以将一个对象变成一个常量,不可被修改,所以定义的 时候必须进行初始 ...

  9. C++之const限定符

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

随机推荐

  1. 如何做rom,体验做rom过程,附图文教程,感谢各位romer

    http://bbs.gfan.com/android-5408130-1-1.html 有人问我,我简单的写一下,来源XDA,运行环境ubuntu 10.4. ubuntu安装很简单,在window ...

  2. JPA 入门程序及相关注解

    1. 概述 JPA(Java Persistence API):用于对象持久化的API; JPA本质上是一种ORM规范,不是ORM框架;提供了一些编程的API接口; Hibernate是实现; 1.1 ...

  3. Django 框架之 Models

    1. 数据库配置 Django默认支持sqlite, mysql, oracle, postgresql 数据库: Django默认使用sqlite数据库,引擎名称:django.db.backend ...

  4. Keras + Ubuntu环境搭建

    安装Theano (环境参数:Ubuntu 16.04.2  Python 2.7) 安装 numpy 和 scipy 1.sudo apt-get install python-numpy pyth ...

  5. go-007-条件语句

    一.概述 条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为 true 来决定是否执行指定语句,并在条件为 false 的情况在执行另外的语句. 1.if结构 if 布尔表达式 { /* ...

  6. HDU3074: Multiply game(线段树单点更新,区间查询)

    题目: 传送门 题解:线段树模板题目. 对递归的题目始终理解不好,我的痛啊,在水的题目都要写很长时间. #include <iostream> #include <string.h& ...

  7. 模块讲解----time与date time(时间模块)

    time和datetime 在python中,通常有一下几种方式来表示时间:1.时间戳:2.格式化时间字符串:3.元祖(struct_time):其中元祖(struct_time分为九个元素) UTC ...

  8. 压力测试sysbench

    sysbench是一个模块化的.跨平台.多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况.目前sysbench代码托管在launchpad上,项目地址:https://launc ...

  9. (二)无状态的web应用(单py的Django占位图片服务器)

    本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃 阅读本文建议了解Django框架的基本工作流程,了解WSGI应用,如果对以上不是很清楚,建议结 ...

  10. Java基础知识陷阱(二)

    本文发表于本人博客. 上次说了一些关于字符串的知识,都是比较基础的,那这次也说下关于对象地址问题,比如传参.先看下面代码: public void changeInt(int a){ a = ; } ...