• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > C++中const用法小结

C++中const用法小结

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了c++ const用法,c++中const的用法,c++ const用法总结,c++中const是什么意思,c++中const等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

const在C++中使用十分广泛,不同位置使用的意义也不尽相同,所以想写篇文章对其做一个总结。

首先,明确const是“不变”这个基本意义,但是不变不意味着什么都不变,下面将会看到。

1. const与变量

基本原则:const变量(对象)不能被修改

const在变量中的引入和魔数有关,所谓“魔数”指的是突然出现的一个常量值(也叫字面值常量)。

for(int i = 0; i < 512; i++)
{
// todo
}

</div>

上例中,512即为魔数,512突然出现在循环中,令人不能得知其意义,所以引入const。

const int length = 512;
for(int i = 0; i < length; i++)
{
// todo
}
</div>

这样就知道循环是在长度范围内。

1.1 const修饰一个变量(或者说对象),使其变成一个常量,表示该变量的值无法再被修改,正因为如此,所以定义一个常量的时候,必须初始化。

1.2 const常量的作用域:

我们知道,在全局作用域内声明一个变量(此处特指非const修饰的变量),其作用于整个程序,在其他文件中也能被引用,原因是在全局作用域声明一个变量,默认是extern修饰的。

在全局作用域内声明一个const变量,默认不是extern修饰,所以其只能作用于本文件内,若要在其他文件中访问,需要显式声明为extern

2. const与引用

基本原则:const引用是指向const变量(对象)的引用

const int ival = 1024;
const int &refVal = ival;

</div>

2.1 const引用可以指向一个相关类型(不是本类型)的const变量

double dval = 3.14;
const int &refVal = dval;

</div>

编译器将double转换成一个临时的int对象,然后让const引用绑定到这个临时对象,所以改变dval的值不会改变refVal,也就是说dval仍然是非const变量,refVal仍然是常量引用。

primer第四版是上面的说法,但我在VS2012中,const也可以指向一个本类型的非const变量,查找资料的原因大概是满足reference-campatible条件。

理论上,我们应该严格遵守,常量引用指向常量对象,非常量引用指向非常量对象,避免出错。

3. const与指针

const与指针的关系分为两种:const修饰的指针和指向const对象的指针,二者const的位置不相同

3.1 指向const对象的指针(const位于指针符号*前面)

对于一个const对象,必须用一个指向const的指针来指向它。原因在于,const修饰使得对象无法被改变,而指针如果不是指向const的指针,则可以通过指针来修改对象,这是不被允许的。

const int ival = 1;
const int *ptrVal = &ival;

</div>

反过来,对于一个指向const对象的指针,可以指向任意一个对象,这个该怎么理解呢?我们首先看看指针赋值的过程:

int *ptr = &val;

</div>

将val的地址赋值给ptr,因为赋值的只是地址,所以不知道ptr所指向的对象是否为const。

如果我们把一个地址赋值给一个指向const的指针,那么指针认为这是一个const的对象,也就是说,ptr指针指向了一个“自认为”是const的对象。

int ival = 1;
const int *ptrVal = &ival;

</div>

上面的程序是正确的,我们需要明确,ival是非const变量,所以我们可以通过给ival赋值更改ival的值。ptrVal指向了一个自认为是const的对象,所以我们无法通过*ptrVal来更改ival的值。

3.2 const修饰的指针(const位于指针符号*后面)

int *const ptr;

</div>

上式声明了一个const类型的指针,表示的意思是指针本身是一个常量,不能被修改。

如何理解?指针本身的值是一个地址,如果指针本身是一个常量,则这个地址值不能被修改,也就是说指针只能指向这个地址,不能指向其他地方。但指针所指向的地址的内容不属于指针本身的值,所以其所指向的内容可以改变。

int ival = 1;
int *const ptr = &ival;
*ptr = 2;          // ok
int ivalTwo = 11;
ptr = &ivalTwo       // error

</div>

综上,可以定义一个指向const对象的const指针

const int *const ptr = &ival;

</div>

3.3 typedef中易出错的const指针

typedef string *ptr;
const ptr s_ptr;

</div>

上式不能直接替换理解为const string *s_prt; 从而认为s_ptr是一个指向const string的指针。
首先,ptr是一个指针,const修饰的是一个指针,所以应该是string *const s_ptr; s_ptr是一个指向string的const指针。

4. const与数组

const与数组的点在于const在定义时必须初始化这个原则,所以使用动态分配数组时,如果数组存储的是const类型的对象,必须进行初始化(使用初始化符号())。

5. const与函数返回值

修饰函数的返回值,用于返回一个常量。

const int foo();

</div>

5.1 返回通过值传递

如果函数返回时采用值传递,比如返回一个int类型,那么函数会把返回的值(比如47)复制到外部临时存储单元中(产生临时副本),所以加const修饰毫无意义

int foo();
const int foo();

</div>

二者完全相同。需要注意的是,值传递产生临时副本,效率低(下面const与函数参数有讲),所以通常采用引用传递来返回。

5.2 返回通过引用传递(并不多见)

如果返回值不是内部类型,通常使用引用传递来返回结果,因为引用传递的是本身,不需要产生临时副本。但需要注意的是,此时仅仅返回一个别名。

ClassType &foo();
const ClassType &foo();

</div>

const修饰的返回引用值,表示函数调用的结果只能赋值给一个同类型的const引用。

5.3 返回通过指针传递

const ClassType *foo();

</div>

表示函数返回一个ClassType类型的指针,这个指针指向一个const对象,指针所指的内容不能被修改,所以函数的返回值只能赋值给指向一个const的同类型的指针。

const ClassType *ptr = foo();  //ok
ClassType *ptr = foo();     //error

</div>

6. const与函数参数

首先需要明确,const修饰的目的就在于保护所修饰的内容不被改变。
在C++中,函数参数分为值传递,指针传递和引用传递。

6.1 值传递

值传递在函数调用时产生一个临时副本,函数中对传入参数的修改和操作是对副本的操作,不改变实参本身的值,所以无需const来保护。
值传递的保护很好,但值传递存在缺点,需要产生临时副本,如果传入的是对象,那么需要进行构造、复制、和析构等操作,效率不高。这时候可以考虑引用传递

void foo1(int x);
void foo2(ClassType instance);     //开销较大
</div>

下面这种保护无意义:

void foo1(const int x);
void foo2(const ClassType instance);  

</div>

6.2 引用传递

通过传入实参的引用,降低开销。因为引用即本身,不需要去产生一个临时副本。

void foo1(int &x);
void foo2(ClassType &ref);

</div>

对于上述两个函数,函数调用和值传递的形式完全一样,不同的是函数内部得到的x和ref是调用传入实参的引用。也正因为如此,引用可以通过函数改变传入的参数来改变实参。这对与实参来说,比较危险,这时候需要通过const修饰来保护传入的引用不被修改。

void foo1(const int &x);
void foo2(const ClassType &ref);

</div>

通常来说,对于基本内部类型,不存在对象的构造等操作,所以下面两种保护参数不被修改的方式效率基本一样。

void foo1(int x);
void foo1(const int &x);

</div>

6.3 指针传递

指针传递在保护参数不被修改上和引用传递是一样的,指针传递还有一个功能是可以扩大接收参数的范围:

void foo1(const ClassT



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C++中的const的使用详解
  • C++ const引用、临时变量 引用参数详解
  • c++中临时变量不能作为非const的引用参数的方法
  • c++ 类中const成员变量的赋值方法
  • C++中const应放在类型前还是后
  • C++中const用法小结
  • C和C++ const的声明差异
  • C++ 中const和复合类型
  • C++ 中const 类型限定符不兼容问题
  • C++ const修饰变量和修饰函数介绍

相关文章

  • 2017-05-28VC编程控件类HTControl之CHTGDIManager GDI资源管理类用法解析
  • 2017-05-28C语言中lseek()函数和fseek()函数的使用详解
  • 2017-05-28C++之异常处理详解
  • 2017-05-28C++实现不能被继承的类实例分析
  • 2017-05-28使用Inotify 监控目录与文件的方法详解
  • 2017-05-28while和for可以相互转换的例子分享
  • 2017-05-28浅谈C++对象组合
  • 2017-05-28用C实现添加和读取配置文件函数
  • 2017-05-28VC实现A进程窗口嵌入到B进程窗口中显示的方法
  • 2017-05-28Cocos2d-x保存用户游戏数据之XML文件是否存在问题判断方法

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 解析bitmap处理海量数据及其实现方法分析
    • C/C++实现快速排序的方法
    • 深入VC回调函数的使用详解
    • 内部排序之堆排序的实现详解
    • C语言基础知识变量的作用域和存储方式详细介绍
    • C++初始化函数列表详细解析
    • 浅谈c++ vector和map的遍历和删除对象
    • c++中虚函数的实现详解
    • 探讨编写int strlen(char *strDest);不允许定义变量的问题
    • 详解C++编程中的析构函数

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有