C++中的static和const
static
-
不考虑类的情况
- 当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。
- 默认初始化为0,包括未初始化的全局静态变量与局部静态变量,都存在全局未初始化区.bss区
- 静态变量在函数内定义,始终存在,且只进行一次初始化,具有记忆性,其作用范围与局部变量相同,函数退出后仍然存在,但不能使用,在下次调用时仍维持上次的值;
- 在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
-
考虑类的情况
- static成员变量:只与类关联,不与类的对象关联。定义时要分配空间,不能在类声明中初始化,必须在类定义体外部初始化,初始化时不需要标示为static;可以被非static成员函数任意访问。
- static成员函数:不具有this指针,无法访问类对象的非static成员变量和非static成员函数;不能被声明为const、虚函数和volatile;可以被非static成员函数任意访问
- static成员函数不能被virtual修饰,static成员不属于任何对象或实例,所以加上virtual没有任何实际意义;静态成员函数没有this指针,虚函数的实现是为每一个对象分配一个vptr指针,而vptr是通过this指针调用的,所以不能为virtual;虚函数的调用关系,this->vptr->ctable->virtual function
const
-
const修饰普通类型的变量
- 阻止一个变量被改变,可以使用const关键字,const常量在定义时必须初始化,之后无法更改
-
const 修饰指针变量
- const 修饰指针指向的内容,指针常量,内容为不可变量
- const 修饰指针,则指针为不可变量,即常量指针
- const 修饰指针和指针指向的内容,则指针和指针指向的内容都为不可变量
-
const参数传递和函数返回值
-
const 修饰函数参数
- 值传递的 const 修饰传递,一般这种情况不需要 const 修饰,因为函数会自动产生临时变量复制实参值,这个时候无论加不加const对实参不会产生任何影响
- const 参数为指针时,可以防止指针被意外篡改
- const参数为引用,自定义类型的参数传递,需要临时对象复制参数,对于临时对象的构造,需要调用构造函数,比较浪费时间,因此我们采取 const 外加引用传递的方法。
-
const 修饰返回值
- const 修饰自定义类型的作为返回值,此时返回的值不能作为左值使用,既不能被赋值,也不能被修改。
- const 修饰返回的指针或者引用,是否返回一个指向 const 的指针,取决于我们想让用户干什么。
-
-
类相关const
- const修饰类的成员变量,表示成员常量,不能被修改,同时它只能在初始化列表中赋值。
- const修饰类的成员函数,则表明其是一个常函数,不能修改类的成员变量
- const对象只能调用const成员函数。
顶层const和底层const
顶层const: 指针本身是个常量,const在*
的右边
底层const: 指针所指的对象是个常量,const在*
的左边
区分作用:
- 当执行对象的拷贝操作时,顶层const不受影响,因为执行拷贝操作并不会改变被拷贝对象的值,但拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换,非常量可以转换为常量,反之不行
- 使用命名的强制类型转换函数const_cast时,只能改变运算对象的底层const
int i = 0;
int *const p1 = &i; // 不能改变p1的值,顶层const
const int ci = 42; // 不能改变ci的值,顶层const
const int *p2 = &ci; // 允许改变p2的值,底层const
const int *const p3 = p2; // 靠右的const是顶层const,靠左的是底层const
const int &r = ci; // 用于声明引用的const都是底层const
i = ci; // 正确:拷贝ci的值,ci是一个顶层const
p2 = p3; // 正确:p2和p3指向的对象类型相同,p3顶层const不影响
int *p = p3; // 错误:p3包含底层const,而p没有
p2 = &i; // 正确:int*能转换成const int*
int &r = ci; // 错误:普通的int& 不能绑定到int常量上
const int &r2 = i; // 正确:const int&可以绑定到普通变量int上
转载自:https://juejin.cn/post/7023353231984033800