作用:
-
Static用于定义静态变量,包括全局和局部的静态变量,两者的共同点:
- 都存储在内存中的静态存储区;
- 都是整个程序结束后才会被释放,否则一直存在,尤其是多次调用时,新一次的调用的初始值为上一次调用后的结果;
不同点:
- 全局静态变量作用域为从定义之处到文件结尾,而局部静态变量作用域为定义之处开始到函数结束,但是函数结束后该局部变量在内存中并不会被销毁,等再次调用该函数时可以继续访问。
2.Static用于定义静态函数;
- 作用于整个.cpp文件中,一般定义于cpp头部;
- 好处:不同cpp文件中用static修饰的同名函数互相不会干扰。(作用域局限于所处文件)
- 静态函数、静态变量不在头文件中定义是因为多个cpp使用该静态函数或者变量,看起来用的是文件全局的变量、或函数,但实际上对于每个cpp来说,输出该变量、函数的地址并不相同,相当于头文件被多少个cpp调用,头文件中的静态变量或函数就被定义了多少次。正确的头文件中的全局变量的定义应该是用extern修饰,例如: extern int a;(此时不能初始化其值)然后在别的cpp中定义一次(例如:int a=1;)即可全局使用
3.Static用于定义类中的静态成员变量、函数
- 静态成员变量相当于被该类的对象共有,同时不会破坏隐藏数据的规则(即会受到public等的限制),
类中定义,类外初始化,使用的时候只需要 类名::变量 或 类对象名. 变量 即可
- 静态成员函数也是被该类的对象共有,使用的时候只需要 类名::函数(参数) 或 类对象名. 函数(参数) 即可;但是需要注意的是一般静态函数中无法调用非静态成员,除非把非静态对象作为参数传入静态函数,如:
不能直接调用的原因是非静态成员只有初始化之后才能调用,如果在类中静态函数里直接 调用时非静态成员尚未初始化,导致报错。将其作为参数传入函数,才能使用。
4.Const的用法
例如:const char * arr = "123";
//字符串123保存在常量区,const本来是修饰arr指向的值不能通过arr去修改,但是字符串“123”在常量区,本来就不能改变,所以加不加const效果都一样
char * brr = "123";
//字符串123保存在常量区,这个brr指针指向的是同一个位置,同样不能通过brr去修改"123"的值
const char crr[] = "123";
//这里123本来是在栈上的,但是编译器可能会做某些优化,将其放到常量区
char drr[] = "123";
//字符串123保存在栈区,可以通过drr去修改
Const:1)修饰常量:
const可以修饰常量,使该常量的值不能改变,局部变量与全局变量都一样,定义时就要赋值。
2)修饰指针:指针不能改变
3)修饰函数:
3.1)const修饰函数的参数● 防止修改指针指向的内容或指针本身;
3.2)const修饰函数的返回值,那么函数返回值(指针)的内容就不能被修改,该返回值只能被附加给加const修饰的同类型返回值(指针)。
4)const修饰成员变量:const修饰类的成员函数,表示成员常量,不能被修改,同时它只能在初始化列表中或初始化时赋值。如: const int nValue=10; //成员常量不能被修改
A(int x): nValue(x) { } ; //只能在初始化列表中赋值
5)const修饰成员函数:则该成员函数不能修改类中任何非const成员函数。一般写在函数的最后来修饰。如: void function()const; //常成员函数, 它不改变对象的成员变量.
a. const成员函数不被允许修改它所在对象的任何一个数据成员。
b. const成员函数能够访问对象的const成员,而其他成员函数不可以。
5.define 、enum和const的区别(编译阶段、安全性、内存占用等)
1.define可以用来定义常量字符、数字和表达式(如:#define a 15+5)
但是需要注意的是这里的定义是替换,如:a*a会被替换成15+5*15+5;(这可能造成计算结果的差异)
Define还可以用来定义简单的函数,如:#define M(y)(y*y)
最后还能用来防止重复定义,如#ifndef __headerfileXXX__
#define __headerfileXXX__
Const用来修饰常类型的对象,修饰部分(先看左侧最近部分,没有再看右侧)
const int* p1 = &Year;
int const *p2 = &Year; //p1和p2是同种类型的,指向内容不能变
int* const p3 = &Year; //p3指针所指向的地址不能变
const int* const p4 = &Year; //p4指针所指向的地址和指向内容都不能变
程序编译的四个阶段:预处理—->编译—->汇编—->链接,最后开始运行。
枚举enum只能以标识符形式表示,不能为数字或字符常量,
enum week {Sun, Mon, Tue, Wed, Thu, Fri, Sat}; // 定义枚举类型week,默认从0开始依次加1
Enum相当于一系列的define操作
在没有显示说明的情况下,枚举常量(也就是花括号中的常量名)默认第一个枚举常量的值为0,往后每个枚举常量依次递增1。或者其中某个赋值之后,后续默认+1 。需要注意的是不能同名
变量是全局变量的情况下, 枚举值的缺省值是0,不是枚举的第一个值。局部变量时候默认值为1。 其他情况,其值是随机的,而且不限定于所列出的枚举值
=0
X1=0,x2=1,x3=10,x4=11,x5=12
总结:#define注重预处理的替换,const倾向于常类型的变量或对象,enum更偏向于一种自定义的数据类型,建议多使用const作为常量表达方式,原因是适用范围广且容易排查错误。
一:区别
(1)就起作用的阶段而言: #define是在编译的预处理阶段起作用,而const是在 编译、运行的时候起作用。
(2)就起作用的方式而言: #define只是简单的字符串替换,没有类型检查。而const有对应的数据类型,是要进行判断的,可以避免一些低级的错误。
(3)就存储方式而言:#define只是进行展开,有多少地方使用,就替换多少次,它定义的宏常量在内存中有若干个备份;const定义的只读变量在程序运行过程中只有一份备份。
(4)从代码调试的方便程度而言: const常量可以进行调试的,define是不能进行调试的,因为在预编译阶段就已经替换掉了。
(1)安全性方面:const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
(2)有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。
(3)const可节省空间,避免不必要的内存分配,提高效率
Struct和class的区别
1内部成员变量及成员函数的默认防控属性
struct默认防控属性是public的,而class默认的防控属性是private的;并且在继承的时候也是struct默认public继承,class默认private继承;
2 class这个关键字还可用于定义模板参数,就像typename。但是strcut不用于定义模板参数;
3 赋值时class无法用{}赋值,但是struct在内部没有构造函数或虚函数的时候可以。