Const用法总结(快速区分指针常量与常量指针)
想当初面试时,面试官问我熟悉C++么?熟悉的话说一下const的用法,然后我就开始凌乱了~
其实const的用处还真不少,好好捋顺一下会有很大的帮助。
有时候我们希望定义一种常量,它的值不能被修改,这个常量既可以防止程序其他地方不小心修改这个值,也能让程序员比较方便的调整这个值的大小。
以往我们很容易想到#define宏定义,现在使用const是个更为不错的选择,因为它有类型,可以进行类型检查。
第一部分:const的初始化
Const值一旦创建后就不能修改,所以const对象必须初始化。
Const int i=0;//正确
Constint i;//错误
Const对象可以用非const对象初始化,也可以付给非const对象,同时也能参与运算,只要初始化后不改变它的值就没问题。
Int i;
Constint j=i;//正确
Intm=j;//正确
第二部分:const的作用域
默认状态下,Const对象仅在文件内有效。所以不同文件的const对象不是同一个对象,即使名字相同,因为这样才能避免重复定义。
那为了使一个非常量表达式的const变量在不同文件之间可以共享,可以使用extern来解决问题。
我们知道关键字extern可以用作对象的声明而不定义。所以我们按如下的方式:
//file.cpp
extern constint temp=fun();
//file.h
extern constint temp;//正确
第三部分:const与引用
引用可以节省拷贝带来的内存损耗。类似起了个别名。
1. 对常量的引用必须要用const引用
Const int c=42;
Int &r1=c; //错误,因为非常量引用可以改变所引用对象,所以这样不合理
Const int&r2=c;//正确,引用与对应的对象都是常量
2. 对const的引用可能并非引用一个const对象
int a=0;
int &r1=a;
const int&r2=a;//正确
r1=0;
r2=0; //错误,r2是常量引用不能修改所引用的值
3. 初始化常量引用时允许用任意表达式(可以是不同类型)作为初始值
Int i=4;
Double b=9.22;
Const int &r1=i;
Const int &r2=b;
Const int&r3=44;
Const int&r4=r1*2;
//以上都是正确的
int &r5=r1*2; //错误,r5是普通的非常量的引用
第四部分:const与指针
1. 与常量引用相似,指向常量的指针必须要用const指针(指向常量的指针)
const int c=42;
int *r1=&c; //错误
const int*r2=&c;//正确
*r2=42;//错误,不能给指针所指对象赋值
2. 常量指针(指向const的指针)和指针常量(const指针)
区分常量指针(指向常量的指针)和指针常量(地址是常量,指针指向的地址不变)
(前两个字作为形容词修饰后两个字。
同时大家也要注意const指针这一说法,不要理解成常量指针)
Int num=0;
Int*const cur=#//一直指向num
Const double pi=3.1415;
Const double * const pip=π//指向常量的常量指针。
*现在举例子说明一下常量指针域指针常量到底如何区分。
1. int const* cur; 常量指针,指向常量的指针
2.Const int * cur; 常量指针,指向常量的指针
3. int*const cur; 指针常量
4. const(int *) cur; //错误,不可以这么写
现在我们可以以*为分界,我们从右向左读取指针变量(cur)最近的关键字,1和2的情况变量紧挨着*(理解为*直接修饰cur),证明该指针不是常量指针,而3中const比*更接近变量,所以3是常量指针(理解为*修饰const cur ,const修饰cur,所以cur是不变的)
这里记忆的方法并不是深入C++原理的方法,不过个人觉得非常有效!!!强烈建议试试!!
虽然没有第四种情况,但是在使用typedef时有一个类似的情况,这里在给出一个例子。
typedef char* pstring;
const pstring cstr=0;
//cstr是一个指向char的常量指针,这句话等价于char* Const cstr=0;
//而不是等价于Const char* cstr=0;
第五部分:const与函数参数
1. 顶层const与底层const
带有const声明的变量本身不变是顶层const,所引用或所指向的对象不变就是底层const。
在进行拷贝操作时,顶层const一般可以忽略,但是底层const不可以忽略。
2. 实参初始化形参时会忽略顶层const
Void fun(const inti)
Void fun(int i)//再次定义则会报错,重复定义,二者其实没什么差别,因为第一个顶层const被忽略
3. 形参的初始化方式和变量的初始化方式一样,可以使用非常量初始化一个底层const,但反过来不
可以
Int i=0;
Const int &j=i;//正确
Int &r1=j;//错误
同理,对于函数int reset(int *a){}
Int i=0;
Const int ci=i;
Reset(&i);//正确
Reset(&ci);//错误
4. 尽量使用常量引用
把函数不会改变的形参定义成普通引用会造成一种可以改变的错觉,而且限制了实参的类型。因为我们上面说了,常量引用可以接受更多种类的赋值,包括表达式,字面值等。有时,还可能出现把常量引用作为参数赋给非常量引用的错误。
下面是C++primer里面的两个例子(有修改,这里不在意功能):
例1:
Int find_char(string&s,char c)
Find_char(“Hello”,’o’);//错误,普通引用无法接收字面值
例2:
Bool isSentence(const string &s)
{
Return find_char(s,’o’);//错误,s是常量引用不能赋给非常量变量
}
第六部分:const与类
1. const成员变量
类中声明变量为const类型。但是不可以初始化,必须要在构造函数初始化列表中初始化。
这样的变量其实只是在一个对象中是不变的,要想在整个类中都不变就得用enum(枚举)
2. const成员函数
这样的成员函数不可以修改数据成员,如果修改成员变量或者调用了其他非const成员函数就会报错。
Const用法总结(快速区分指针常量与常量指针)的更多相关文章
- C++之常指针,指针常量,函数指针,const用法总结
1.const char *p,char const *p,char * const p 对于C++而言,没有const * 修饰符,所以,const只可以修饰类型或者变量名.因而const char ...
- const指针和指向常量的指针
先看下面六种写法: . const int p; . const int *p; . int const* p; . int * const p; . const int * const p; . i ...
- 【转】const int *p和int * const p的区别(常量指针与指向常量的指针)
[转]作者:xwdreamer 出处:http://www.cnblogs.com/xwdreamer 对于指针和常量,有以下三种形式都是正确的: const char * myPtr = &am ...
- c++中指针常量,常指针,指向常量的常指针区分
const char * myPtr = &char_A;//指向常量的指针 char * const myPtr = &char_A;//常量的指针 const char * con ...
- C++ const 常量和常指针
常量,该指针所指向的值为只读 ; const int * p = &a; 常指针,该指针的值为只读,不可再指向其他地址 const * const p = &a; 常值,常指针 con ...
- 指针与 const --- 指针常量与常量指针
注:该文主要来源于 网易公开课之<C++ 程序设计入门(上)>课件. 在 C 语言标准中,const 修饰的变量称之为 只读变量, 在 C++ 语言标准中,const 修饰的变量称之为 常 ...
- C++中const用法详解
本文主要内容来自CSDN论坛: http://bbs.csdn.net/topics/310007610 我做了下面几点补充. 补充: 1. 用const声明全局变量时, 该变量仅在本文件内可见, 类 ...
- const用法详解(转)
http://www.cnblogs.com/StudyRush/archive/2010/10/06/1844690.html 面向对象是C++的重要特性. 但是c++在c的基础上新增加的几点优化也 ...
- C++中指针常量和常量指针的区别
在C++学习使用过程中,每个人都不可避免地使用指针,而且都或多或少的接触过常量指针或指针常量,但是对这两个的概念还是很容易搞糊涂的. 本文即是简单描述指针常量和常量指针的区别. 常量指针 定义: 又叫 ...
随机推荐
- nditer —— numpy.ndarray 多维数组的迭代
1. Single array iteration >>> a = np.arange(6).reshape(2,3) >>> for x in np.nditer ...
- jQuery中对象的构建
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 组态档(configuration file)与建构档
组态档,或者叫 configuration file,配置文件.组态档是用一种建构软件专用的特殊编程语言写的 CMake 脚本. 使用组态档能改变程序的设置,而不用重新编译程序. CMake 的组态档 ...
- Android中使用sqlite3操作SQLite
SQLite库包含一个名字叫做sqlite3的命令行,它可以让用户手工输入并执行面向SQLite数据库的SQL命令.本文档提供一个样使用sqlite3的简要说明. 一.创建数据库: 1.将sqlit ...
- VS编译环境中TBB配置和C++中lambda表达式
TBB(Thread Building Blocks),线程构建模块,是由Intel公司开发的并行编程开发工具,提供了对Windows,Linux和OSX平台的支持. TBB for Windows ...
- c语言学习笔记(5)——进制
进制 1.什么叫进制? 逢n进1: 2.把r进制转成十进制 a*r^0+b*r^1+c*r^2..... 3.把十进制转成r进制 185----->(r进制) 185不停的除r取余,最后把余数 ...
- WPF-- 合并资源字典
原文:WPF-- 合并资源字典 1. 合并多个外部资源字典成为本地字典 语言 XAML 示例代码 <Page.Resources> <ResourceDicti ...
- 在python3下用PIL做图像处理
Python Imaging Library (PIL)是python下的图像处理模块,支持多种格式,并提供强大的图形与图像处理功能. 目前PIL的官方最新版本为1.1.7,支持的版本为python ...
- 方阵的迹(trace)及其微分(导数)
trace 的一个十分重要的性质在于线性性, Tr(A+B)=Tr(A)+Tr(B)Tr(cA)=cTr(A) 1. 基本性质 Tr(A)=Tr(AT) Tr(AB)=Tr(BA) Tr(ABC)=T ...
- Vue-cli入门(一)——项目搭建
Vue-cli入门(一)——项目搭建 前言: Vue-cli是一款基于vue的项目脚手架工具,其集成了webpack环境和主要的依赖,对于我们的项目搭建.开发.打包.维护管理等都是非常的方便. 主要内 ...