C++那些事笔记——const那些事
前言
C++那些事
这是一个适合新手学习的C++开源项目
[Github地址] (https://github.com/Light-City/CPlusPlusThings)
const那些事
1.const的作用
可以定义常量
创建常量的通用格式如下:
1
const type name = value;
当你在声明常量的时候必须对它进行初始化,如果在声明常量时没有对它进行初始化,则该常量的值是不确定的,且无法修改。
类型检查
const
常量与#define
宏定义常量的区别:- const能够明确指定类型,并且可以使用C++的作用域规则将定义限制在特定的函数或文件中
- const定义的变量只有类型为整型或枚举时,且以常量表达式初始化时才能作为常量表达式
- 其他情况下它只是一个const限定的变量而不是一个常量
防止修改,起保护作用,增加程序健壮性
可以节省空间,避免不必要的浪费
- const定义常量从汇编角度来看,只是给出了对应的内存地址,而不是像#define一样给出的是立即数
- const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中却有多份拷贝
2.const对象默认为局部变量
- 未被const修饰的变量不需要extern显式声明
- const常量需要显式声明extern,并且需要做初始化
- 常量在定义后就不能被修改,所以定义时必须初始化
3.指针与const
如果const在*的左侧,则const就是用来修饰指针所指向的变量,即指针指向常量
1
2const char * a; //指向常量的指针。
char const * a; //同上- 对于指向常量的指针,不能通过指针来修改对象的值
- 允许把非const对象的地址赋给指向常量的指针,当要修改其值时需要像通过非const指针修改
1
2
3
4int val = 3;
const int *ptr = &val; //ok
int *ptr1 = &val;
*ptr = 4;- 不能使用void *指针去保存const对象的地址,必须使用const void *类型的指针保存const对象的地址
1
2
3const int p = 10;
const void * vp = &p;
void *vp = &p; //error如果const在*的右侧,则const就是修饰指针本身,即指针本身就是常量,称为常指针
常指针在定义是必须进行初始化,且常指针的值不能再进行修改,但是可以通过非const指针来修改
1
2
3
4int num=0;
int * const ptr=# //const指针必须初始化,且const指针的值不能修改
int * t = #
*t = 1;因为此时const修饰的是指针本身,ptr指向的还是一个变量,只是不能通过ptr修改它的值,所以不能将const对象的地址赋值给ptr
上述情况若改为const int *ptr或const int *const ptr就可以正常运行
上述两种情况的结合就是指向常量的常指针
ptr是一个const指针,然后它指向了一个int类型的const对象
1
2const int p = 3;
const int * const ptr = &p;
4.函数与const
const修饰函数返回值
这个和cosnt修饰普通变量和指针含义基本相同,但没有意义
const修饰函数参数
输入参数只是”值复制”,对原变量没有影响,无需保护,即使传入的形参是指针也是一样,const修饰的是指针本身,它所指向的地址还是可变的,所以此操作无意义
1
2void func(const int var);
void func(int *const var);参数指针所指内容为常量不可变
1
void StringCopy(char *dst, const char *src);
dst是输出参数,src是输入参数,当我们需要保护src指向对象的值时,将src用const修饰,这样当函数体的语句试图修改src的值时,编译器将指出错误
参数为引用,增加效率同时防止修改
1
void func(const A &a)
对于非内部数据类型的参数而言,象void func(A a) 这样声明的函数注定效率比较低。因为函数体内将产生A 类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将消耗时间
为了提高效率,可以将函数声明改为void func(A &a),因为“引用传递”仅借用一下参数的别名而已,不需要产生临时对象
但是函数void func(A &a) 存在一个缺点:“引用传递”有可能改变参数a,这是我们不期望的
解决这个问题很容易,加const修饰即可,因此函数最终成为 void func(const A &a)。
以此类推,是否应将void func(int x) 改写为void func(const int &x),以便提高效率?
没有必要,因为内部数据的参数不存在构造、析构之内的过程,“值传递”和“引用传递”的效率几乎相当
5.类与const
在一个类中,任何不会修改数据成员的函数都应该声明为const类型,如果在编写const成员函数时,不慎修改数据成员,或者调用了其它非const成员函数,编译器将指出错误,这无疑会提高程序的健壮性
使用const关键字进行说明的成员函数,称为常成员函数,只有常成员函数才有资格操作常量或常对象,没有使用const关键字进行说明的成员函数不能用来操作常对象
对于类中的const成员变量必须通过初始化列表进行初始化