C++ const & static 关键字
const
用法1 : 修饰基本数据类型
1 |
|
用法2 : const修饰指针变量*及引用变量&
2.1 : 指针*
1 | const int* a = & [1] //非常量数据的常量指针 指针常量 |
- 如果const位于星号*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
- 如果const位于星号*的右侧,const就是修饰指针本身,即指针本身是常量。
- 因此,[1]和[2]的情况相同,都是指针所指向的内容为常量,这种情况下不允许对内容进行更改操作,如不能*a = 3 ;
- [3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的;
- [4]为指针本身和指向的内容均为常量。
2.2 : 引用&
1 | int const &a=x; |
- 这两种定义方式是等价的,此时的引用a不能被更新。如:a++ 这是错误的。
用法3 : const应用到函数中
3.1 : 作为参数的const修饰符
- void fun0(const A* a ); void fun1(const A& a)
- 调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化,如形参为const A* a,
- 则不能对传递进来的指针的内容进行改变,保护了原指针所指向的内容;如形参为const A& a,则不能对传递进来的引用对象进行改变,保护了原对象的属性。
- [注意]:参数const通常用于参数为指针或引用的情况;
3.2 : 作为函数返回值的const修饰符
- const A fun2( ); const A* fun3()
- 这样声明了返回值后,const按照”修饰原则”进行修饰,起到相应的保护作用。
- 返回值不可以被修改
3.3 : 配合 class
使用
- 不能修改所在类的的任何变量
mutable
关键字1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class Entity
{
private:
int m_X;
int* m_Y;
// 加入一个小插曲
int* m_Z, m_M; // 这两个值中,第一个 m_Z 是指针,而第二个是 int 数,需要改成 int* m_Z, *m_M; 这样两个都是指针
mutable int var;
public:
// 这种 const 用法只可以在 class 的 function 中使用
int GetX() const
{
m_X = 34; // error, 无法修改其值
var = 1; // mutable 关键字修饰,就可以进行修改
return m_X;
}
// 返回一个 int 指针,其指向 & 具体数值都不可以改变
// 最后一个 const 表示无法在函数中修改值
const int* const GetY() const
{
return m_Y;
}
int* GetZ()
{
return m_Z;
}
};
// 此处函数对 e 进行只读操作,传入 const reference, 无需拷贝
void Print(const Entity& e)
{
std::cout << e.GetX() << std::endl;
std::cout << *e.GetY() << std::endl;
std::cout << *e.GetZ() << std::endl; // error, 因为传入的 e 是 const,因此只只可以调用 GetX,GetY
}
// 程序的主函数
int main( )
{
Entity e;
std::cin.get();
return 0;
}
其他用法
class 中使用 const
- 对const成员变量的初始化,不能在变量声明的地方,必须在类的构造函数的初始化列表中完成,即使是在构造函数内部赋值也是不行的。
1
2
3
4
5
6
7
8
9
10
11class Test
{
private:
const int a;
const int b;
public:
Test(int a)
:a(a), b(12)
{
}
}
使用static const
1 |
|
static
- static 可以修饰 变量 & 函数
- static 可以出现在 class内部 & class外部
在 class/struct 内部
- static修饰的
类成员(包括变量 & 函数)
属于类,不属于对象
修饰类中成员 - 类的共享数据
static类对象必须要在类外进行初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using namespace std;
class Entity{
public:
static int x;
void print()
{
cout << x << endl;
}
};
int Entity::x; // static类对象的初始化
int main()
{
Entity e1;
Entity e2;
e1.x=1;
e2.x=2;
e1.print();
e2.print();
}
修饰类中成员函数
- 由于static修饰的类成员属于类,不属于对象,
因此static类成员函数是没有this指针的,this指针是指向本对象的指针。
- 正因为没有this指针,所以static类成员函数,不能访问非static的类成员,只能访问 static修饰的类成员。
在 class/struct 外部
- 表示只在当前的编译单元引用
static 出现在 .cpp
文件中
在demo1.cpp中
1
static int x = 7;
在demo2.cpp中
1
2
3
4
5
6
7
8
9
using namespace std;
int x;
function main()
{
cout << x << endl;
}编译的时候就会报错,因为x只在demo1.cpp中才可以被使用
类似的,function 和 var 有类似的用法,static 的 function 只可以在当前的解释单元被使用
static 出现在 .h
文件中
- 如果在 头文件 中申明 static变量
- 那么每一个include的文件都会有一个单独的 static 变量,因为 include 就相当于将这段代码copy进去
局部 static变量
- 主要关注点变量的生命周期
- 注意 static 关键字在 function 中的用法
demo1
1 | function test() |
- x变量只会创建一次
- 每次调用test函数,x都会增加,打印的值也会增加
静态局部变量
在全局/静态区分配内存空间静态局部变量
在程序执行到该对象的声明处时被首次初始化,之后的函数调用不再进行初始化静态局部变量
一般在声明处初始化,若没有显式初始化,会被OS自动初始化为0- 它始终驻留在全局/静态区,直到程序运行结束,但其作用域为局部作用域,也就是不能在函数体外面使用它
Tips
全局数据中的变量
如果没有显示的初始化会自动被程序初始化为0(这个特性非静态全局变量也有),而在函数体内声明的变量如果不显示初始化则会使一个随机值