const和typedef的常见用法详解
一、说说const
一般而言,const主要是用来防止定义的对象再次被修改,定义对象变量时要初始化变量。
常见用法如下:
1.用于定义常量变量,这样这个变量在后面就不可以再被修改
const int Val = 10;
//Val = 20; //错误,不可被修改
2. 保护传参时参数不被修改,如果使用引用传递参数或按地址传递参数给一个函数,在这个函数里这个参数的值若被修改,
则函数外部传进来的变量的值也发生改变,若想保护传进来的变量不被修改,可以使用const保护
void fun1(const int &val)
{
//val = 10; //出错
}
void fun2(int &val)
{
val = 10; //没有出错
}
void main()
{
int a = 2;
int b = 2;
fun1(a); //因为出错,这个函数结束时a的值还是2
fun2(b);//因为没有出错,函数结束时b的值为10
}
如果只想把值传给函数,而且这个不能被修改,则可以使用const保护变量,有人会问为什么不按值传递,按值传递还需要把这个值复制一遍,
而引用不需要,使用引用是为了提高效率//如果按值传递的话,没必要加const,那样根本没意义
3. 节约内存空间,
#define PI 3.14 //使用#define宏
const double Pi = 3.14 //使用const,这时候Pi并没有放入内存中
double a = Pi; //这时候才为Pi分配内存,不过后面再有这样的定义也不会再分配内存
double b = PI; //编译时分配内存
double c = Pi; //不会再分配内存,
double d = PI; //编译时再分配内存
const定义的变量,系统只为它分配一次内存,而使用#define定义的常量宏,能分配好多次,这样const就很节约空间
4.类中使用const修饰函数防止修改非static类成员变量
class
{
public:
void fun() const //加const修饰
{
a = 10; //出错,不可修改非static变量
b = 10; //对,可以修改
}
private:
int a ;
static int b;
}
5.修饰指针
const int *A; 或 int const *A; //const修饰指向的对象,A可变,A指向的对象不可变
int *const A; //const修饰指针A, A不可变,A指向的对象可变
const int *const A; //指针A和A指向的对象都不可变
6.修饰函数返回值,防止返回值被改变
const int fun();
接收返回值的变量也必须加const
const int a = fun(); //接收的变量也要是const的,int a = fun()是错误的
7.修饰类的成员变量
使用const修饰的变量必须初始化,在类中又不能在定义时初始化,
如;
class
{
private:
int a = 10;
const int b = 10;
static const int c = 10;
//这样初始化都是错的,
}
初始化const int类型(没有static),在类的构造函数上初始化
Class Test
{
Public:
Test():b(23) //构造函数上初始化b的值为23
{
}
private:
const int b ;
}
初始化staticconst int这个类型的(带有static的),在类的外面初始化
class Test
{
private:
static const int c;
}
const int Test::c=10; //类的外部初始化c为10
8.const定义的对象变量只能作用于这个程序该C/C++文件,不能被该程序的其他C/C++文件调用,
如file1.cpp中 const int val;
在file2.cpp中, extern intval; //错误,无法调用,
要想const定义的对象变量能被其他文件调用,定义时必须使用extern修饰为
extern const int val;
非const变量默认为extern,要是const能被其他文件访问必须显示指定为extern
二、说说typedef
(C++Primer Plus,p149,p248等有相关论述)
以前简单地以为typdef的用法不过是typedef A B,即把类型B作为类型A的一个新名字。但是碰到像typedef string *pstring或者是typedef int int_array[4]这样的定义就比较容易误解。
常见难点用法如下:
1)用typedef简化指向多维数组的指针的定义
首先,以一维数组为例:
比如typedef int int_array[4],如果去掉前面的typedef那么定义的是一个叫做int_array的含有4个元素的数组。而前面加上typedef以后,int_array就变成了含有4个元素的数组类型的替代名。以后要有int_array ia;这句话我们就知道它等同于int ia[4];
二维数组的例子解读可参考:typedef和const之间的trap
2)用typedef简化函数指针的定义
例如:
typedef bool (*cmpFcn)(conststring &, const string &);
该定义表示 cmpFcn 是一种指向函数的指针类型的名字。该指针类型为“指向返回bool类型并带有两个const string引用形参的函数的指针”。在要使用这种函数指针类型时,只需直接使用cmpFcn即可,不必每次都把整个类型声明全部写出来。如:用新得到的类型来定义两个新的函数指针pf1和pf2,
cmpFcn pf1;
又假设给出以下语句:
typedef string *pstring;
const pstring cstr;
很多人都错误地认为是:
const string *cstr;//const pstring 是一种指针,指向string 类型的 const 对象
错误的原因在于将 typedef 当做文本扩展了。声明 const pstring 时,const 修饰的是pstring的类型,这是一个指针。因此,该声明语句应该是把cstr定义为指向string 类型对象的const指针,这个定义等价于:string *const cstr;
3) 用typedef简化复杂类型的定义
篇幅有限,更详细的用法解读推荐参阅:C++ typedef用法小结(强烈推荐)
const和typedef的常见用法详解的更多相关文章
- STL priority_queue 常见用法详解
<算法笔记>学习笔记 priority_queue 常见用法详解 //priority_queue又称优先队列,其底层时用堆来实现的. //在优先队列中,队首元素一定是当前队列中优先级最高 ...
- STL pair 常见用法详解
<算法笔记>学习笔记 pair 常见用法详解 //pair是一个很实用的"小玩意",当想要将两个元素绑在一起作为一个合成元素, //又不想因此定义结构体时,使用pair ...
- STL stack 常见用法详解
<算法笔记>学习笔记 stack 常见用法详解 stack翻译为栈,是STL中实现的一个后进先出的容器.' 1.stack的定义 //要使用stack,应先添加头文件#include &l ...
- STL queue 常见用法详解
<算法笔记>学习笔记 queue 常见用法详解 queue翻译为队列,在STL中主要则是实现了一个先进先出的容器. 1. queue 的定义 //要使用queue,应先添加头文件#incl ...
- STL map 常见用法详解
<算法笔记>学习笔记 map 常见用法详解 map翻译为映射,也是常用的STL容器 map可以将任何基本类型(包括STL容器)映射到任何基本类型(包括STL容器) 1. map 的定义 / ...
- STL string 常见用法详解
string 常见用法详解 1. string 的定义 //定义string的方式跟基本数据类型相同,只需要在string后跟上变量名即可 string str; //如果要初始化,可以直接给stri ...
- STL set 常见用法详解
<算法笔记>学习笔记 set 常见用法详解 set是一个内部自动有序且不含重复元素的容器 1. set 的定义 //单独定义一个set set<typename> name: ...
- STL vector常见用法详解
<算法笔记>中摘取 vector常见用法详解 1. vector的定义 vector<typename> name; //typename可以是任何基本类型,例如int, do ...
- [js高手之路] es6系列教程 - promise常见用法详解(resolve,reject,catch,then,all,race)
关于promise我在之前的文章已经应用过好几次,如[js高手之路]Node.js+jade+express+mongodb+mongoose+promise实现todolist,本文就来讲解下pro ...
随机推荐
- Maven配置本地库加载ojdbc14-10.2.0.4.0.jar文件
因为ojdbc14-10.2.0.4.0.jar是要收费的,所以Maven的远程库里没有这个资源,只能通过配置本地库来加载到J2EE工程里,做法如下: 第一步:在网上下载ojdbc14.jar,然 ...
- NodeHandles
os::NodeHandle类有两个作用: 第一.它在roscpp程序内提供了一种RAII(Resource Acquisition Is Initialization)类型式启动和关闭内部节点的方法 ...
- switchable图片切换
前提: 最近由于项目的需要jquery "switchable图片切换"效果 所以趁着周末有空时间研究下 ,以前工作都依赖于kissy框架,所以也没有综合的写过类似的,如下图所示效 ...
- Centos7-kafka-2.12安装验证
1.下载Kafka 官网:https://kafka.apache.org/ 2.安装脚本 #解压 tar zxf kafka_2.-.tgz -C /usr/local mv /usr/local/ ...
- Java基础—异常
一.概念 异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的. 异常体 Throwable:所有异常类的超类 Error:它表示不希望被程序捕获或者是程序无法处理的错误 ...
- 20155320 Exp6 信息搜集与漏洞扫描
20155320 Exp6 信息搜集与漏洞扫描 [实验后回答问题] (1)哪些组织负责DNS,IP的管理. 全球根服务器均由美国政府授权的ICANN统一管理,负责全球的域名根服务器.DNS和IP地址管 ...
- flask+socketio+echarts3 服务器监控程序(基于后端数据推送)
本文地址:http://www.cnblogs.com/hhh5460/p/7397006.html 说明 以前的那个例子的思路是后端监控数据存入数据库:前端ajax定时查询数据库. 这几天在看web ...
- Scala学习(二)练习
Scala控制结构和函数&练习 1. 一个数字如果为正数,则它的signum为1:如果是负数,则signum为-1:如果为0,则signum为0:编写一个函数来计算这个值 简单逻辑判断: 测试 ...
- libgdx学习记录20——多线程MultiThread资源处理
在libgdx中,一般的逻辑流程都在rende()函数中执行,这个函数是由opengl的渲染线程调用的,一般的图形显示和逻辑处理都在这个线程中. 一般情形下,在这个线程中处理就行了.但是当某些逻辑处理 ...
- libgdx学习记录7——Ui
libgdx中的UI设计主要通过其对应的Style类进行实现,也可以通过skin实现.如果没有编辑好的skin文件,可以创建一个默认的skin,再添加已经设计好的style类即可,然后在需要使用的地方 ...