创作人QQ:851301776,邮箱:[email protected],欢迎大家一起技术交流,本博客主要是自己学习的心得体会,只为每天进步一点点!
个人座右铭:
1.没有横空出世,只要厚积一定发。
2.你可以学历不高,你可以不上学,但你不能不学习
一、const
1.用const定义和声明变量
使用const定义和声明的变量为常量,也有人叫“常变量”。意思是存储变量内存中的值无能改变,只读的。汇编当中,我们在使用变量的时候,本质是从内存中把值读取到寄存器。 而写入,是先从内存中拷贝一个零时变量给到寄存器,然后对临时变量进行变化操作,然后写会内存,const修饰了只是阻断了不允许把对临时变量进行变化操作。
因为已经是常量了,所以在定义时,必须给变量初始化。
在生存周期内变量的值无法改变。
demo:
const int a = 100; //定义加初始化
++a; //错误的,常量无法修改
2.const修饰指针
int *p;
两层意思如下:
(1)首先p是指针类型的(指针也是一种数据类型)
(2)int是用来修饰 p将来所指向的变量(变量的类型必须是int类型的,这里不考虑强转)
主要有以下三种写法:
const int *a = &b; //第一种
int const *a = &b; //第二种
int *const a = &b; //第三种
第一种和第二种的写法,含义是一样的
const int *a = &b;指向常量的指针
通俗点就是:
定义的时候:领结婚证了,嫁给你了。
进程运行的时候:你想要孩子,你自己生,你想要富裕,自己去劳动。你要是不过了,她就改嫁了,改嫁几次,就说不准了。
进程结束了:死了和任何一位前夫都分开了,生命周期结束。
解释:
- a:是一个指针,可以改变a的指向。(a = &c);
- const int :表示b是常量,不能通过++(*a)改变b的值。但是可以通过b++改变b的值(b本身是int型的)。
int *const a = &b; 指针常量
通俗点说就是:
定义的时候:领结婚证了,嫁给你了
进程运行的时候:可以给你生小孩,可以做家务,但是就一句誓言生是你的人,无论你如何待我,不离不弃,天荒地老,海枯石烂。
进程结束了:死了也就分开了,是不是你的鬼就不知道了
解释:
- const a:是一个指针常量,可以通过++(*a)改变b的值,但是不能改变a的指向,比如之后(a = &c),就是错误的。
- int:表示b的类型是int型的
3.const修饰函数
(1)const 修饰形参
修饰新参时,该形参该函数作用域内为常量, 不可以改变其值。
(2)const修饰返回值
const修饰的返回值,一般返回的都是指针或者引用,也表示常量,不可以通过返回值修改内部数据。
二、static
1.修饰局部变量
static修饰局部变量时,使得被修饰的变量成为静态变量,存储在静态区。存储在静态区的数据生命周期与程序相同,在main函数之前初始化,在程序退出时销毁。(无论是局部静态还是全局静态)
简单理解就是:函数内,声明并定义了一个局部变量,局部变量的真正销毁是:main函数结束。 并是不函数调用结束,局部变量销毁。 延长了局部变量的生命周期。
2.修饰全局变量
全局变量本来就存储在静态区,因此static并不能改变其存储位置。但是,static限制了其链接属性。被static修饰的全局变量只能被该包含该定义的文件访问(即改变了作用域)。
简单理解就是:static修饰的全局变量,只能在当前文件访问。
3.修饰函数
修饰函数,只能在该函数的定义文件中被访问。 主要目的限制作用域为当前文件。
4.修饰成员变量
用static修饰类的数据成员使其成为类的全局变量,会被类的所有对象共享,包括派生类的对象,所有的对象都只维持同一个实例。 因此,static成员必须在类外进行初始化(初始化格式:int base::var=10;),而不能在构造函数内进行初始化,不过也可以用const修饰static数据成员在类内初始化
5.修饰成员函数
用static修饰成员函数,使这个类只存在这一份函数,所有对象共享该函数,不含this指针,因而只能访问类的static成员变量。静态成员是可以独立访问的,也就是说,无须创建任何对象实例就可以访问。例如可以封装某些算法,比如数学函数,如ln,sin,tan等等,这些函数本就没必要属于任何一个对象,所以从类上调用感觉更好,比如定义一个数学函数类Math,调用Math::sin(3.14);还可以实现某些特殊的设计模式:如Singleton;
注意:不可以同时用const和static修饰成员函数
6.隐匿
当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。但是加了static后,就不具有全局可见性了,利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏。
三、extern
extern本身的意思是全局的
1.extern 修饰变量的声明
意思是:此变量已经在其他地方做定义
举例:在a.c中定义了,int ex, 并且对ex进行操作; 可以在b.c中声明extren int ex,b.c可以访问ex
2.extern修饰函数的声明
其实本质上讲,函数名是一个地址。如果文件a.c中引用add函数,但是add函数在b,c中定义,如果懒得找头文件。可以在a.c中声明函数:extern void add(void);
注意看hello.h都已经屏蔽。
extern声明的函数:链接的时候会在所有的.o文件中去找
四、inline
inline修饰的函数表示内联函数。
内联函数:编译器在编译的时候,会把此函数拷贝到调用的位置,但不是加了inline编译器就一定会拷贝,和编译器本身判断有关。
内联函数适合:函数简单(不是代码量少,执行简单)、调用频繁。
五、volatile
volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。
比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。声明时语法:volatile int vInt; 当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。
volatile用在如下的几个地方:
- 中断服务程序中修改的供其它程序检测的变量需要加 volatile;
- 多任务环境下各任务间共享的标志应该加 volatile;
- 存储器映射的硬件寄存器通常也要加 volatile 说明,因为每次对它的读写都可能由不同意义;
1 volatile 指针
和 const 修饰词类似,const 有常量指针和指针常量的说法,volatile 也有相应的概念:
修饰由指针指向的对象、数据是 const 或 volatile 的:
const char* cpch;
volatile char* vpch;
指针自身的值——一个代表地址的整数变量,是 const 或 volatile 的:
char* const pchc;
char* volatile pchv;
注意:
(1) 可以把一个非volatile int赋给volatile int,但是不能把非volatile对象赋给一个volatile对象。
(2) 除了基本类型外,对用户定义类型也可以用volatile类型进行修饰。
(3) C++中一个有volatile标识符的类只能访问它接口的子集,一个由类的实现者控制的子集。用户只能用const_cast来获得对类型接口的完全访问。此外,volatile向const一样会从类传递到它的成员。
3.多线程下的volatile
有些变量是用 volatile 关键字声明的。当两个线程都要用到某一个变量且该变量的值会被改变时,应该用 volatile 声明,该关键字的作用是防止优化编译器把变量从内存装入 CPU 寄存器中。如果变量被装入寄存器,那么两个线程有可能一个使用内存中的变量,一个使用寄存器中的变量,这会造成程序的错误执行。volatile 的意思是让编译器每次操作该变量时一定要从内存中真正取出,而不是使用已经存在寄存器中的值.
六、其他
1.asm (指令字符串):允许在 C++ 程序中嵌入汇编代码。
2.auto(自动,automatic):是存储类型标识符,表明变量"自动"具有本地范围,块范围的变量声明(如for循环体内的变量声明)默认为auto存储类型。
3.bool(布尔)类型:C++ 中的基本数据结构,其值可选为 true(真)或者 false(假)。C++ 中的 bool 类型可以和 int 混用,具体来说就是 0 代表 false,非 0 代表 true。bool 类型常用于条件判断和函数返回值。
4.break(中断、跳出):用在switch语句或者循环语句中。程序遇到 break 后,即跳过该程序段,继续后面的语句执行。
5.case:用于 switch 语句中,用于判断不同的条件类型。
6.catch 和 try 语句一起用于异常处理。
7.try(尝试)用于实现 C++ 的异常处理机制。可以在 try 中调用可能抛出异常的函数,然后在 try 后面的 catch 中捕获并进行处理。
8.class(类):是 C++ 面向对象设计的基础。使用 class 关键字声明一个类。
9.const_cast用法:该运算符用来修改类型的 const 或 volatile 属性。除了 const 或 volatile 修饰之外, type_id 和 expression 的类型是一样的。常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。
const_cast<type_id> (expression)
10.continue(继续):关键字用于循环结构。它使程序跳过代码段后部的部分,与 break 不同的是,continue 不是进入代码段后的部分执行,而是重新开始新的循环。因而它是"继续循环"之意,不是 break(跳出)。
11.default(默认、缺省):用于 switch 语句。当 switch 所有的 case 都不满足时,将进入 default 执行。default 只能放在 switch 语句所有的 case 之后,并且是可选的。
12.dynamic_cast(动态转换),允许在运行时刻进行类型转换,从而使程序能够在一个类层次结构安全地转换类型。dynamic_cast 提供了两种转换方式,把基类指针转换成派生类指针,或者把指向基类的左值转换成派生类的引用。
13.enum(枚举)类型,给出一系列固定的值,只能在这里面进行选择一个。
14.union(联合),类似于 enum。不同的是 enum 实质上是 int 类型的,而 union 可以用于所有类型,并且其占用空间是随着实际类型大小变化的。
15.struct(结构)类型:类似于 class 关键字,与 C 语言兼容(class 关键字是不与 C 语言兼容的),可以实现面向对象程序设计。
16.explicit(显式的)的作用是"禁止单参数构造函数"被用于自动型别转换,其中比较典型的例子就是容器类型。在这种类型的构造函数中你可以将初始长度作为参数传递给构造函数。
17.export:为了访问其他编译单元(如另一代码文件)中的变量或对象,对普通类型(包括基本数据类、结构和类),可以利用关键字 extern,来使用这些变量或对象时;但是对模板类型,则必须在定义这些模板类对象和模板函数时,使用标准 C++ 新增加的关键字 export(导出)。
18.friend(友元):声明友元关系。友元可以访问与其有 friend 关系的类中的 private/protected 成员,通过友元直接访问类中的 private/protected 成员的主要目的是提高效率。友元包括友元函数和友元类。
19.mutable(易变的):是 C++ 中一个不常用的关键字。只能用于类的非静态和非常量数据成员。由于一个对象的状态由该对象的非静态数据成员决定,所以随着数据成员的改变,对像的状态也会随之发生变化。如果一个类的成员函数被声明为 const 类型,表示该函数不会改变对象的状态,也就是该函数不会修改类的非静态数据成员。但是有些时候需要在该类函数中对类的数据成员进行赋值,这个时候就需要用到 mutable 关键字
20.namespace(命名空间):用于在逻辑上组织类,是一种比类大的结构。
21.operator(操作符):用于操作符重载。这是 C++ 中的一种特殊的函数。
22.private(私有的),C++ 中的访问控制符。被标明为 private 的字段只能在本类以及友元中访问。
23.protected(受保护的),C++ 中的访问控制符。被标明为 protected 的字段只能在本类以及其继承类和友元中访问。
24.public(公有的),C++ 中的访问控制符。被标明为 public 的字段可以在任何类
25.register(寄存器):声明的变量称着寄存器变量,在可能的情况下会直接存放在机器的寄存器中;但对 32 位编译器不起作用,当 global optimizations(全局优化)开的时候,它会做出选择是否放在自己的寄存器中;不过其它与 register 关键字有关的其它符号都对32位编译器有效。
26.reinterpret_cast:type-id 必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。
reinpreter_cast<type-id> (expression)
27.signed(有符号):表明该类型是有符号数,和 unsigned 相反。数字类型(整型和浮点型)都可以用 signed 修饰。但默认就是 signed,所以一般不会显式使用。
28.unsigned(无符号),表明该类型是无符号数,和 signed 相反。
29.sizeof:由于 C++ 每种类型的大小都是由编译器自行决定的,为了增加可移植性,可以用 sizeof 运算符获得该数据类型占用的字节数。
30.static_cast
static_cast < type-id > ( expression )
该运算符把 expression 转换为 type-id 类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
- 用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。
- 用于基本数据类型之间的转换,如把 int 转换成 char,把 int 转换成 enum。这种转换的安全性也要开发人员来保证。
- 把空指针转换成目标类型的空指针。
- 把任何类型的表达式转换成void类?
注意 static_cast 不能转换掉 expression 的 const、volitale、或者 __unaligned 属性。
31.template(模板):C++ 中泛型机制的实现。
32.this: 返回调用者本身的指针。
33.throw(抛出):用于实现 C++ 的异常处理机制,可以通过 throw 关键字"抛出"一个异常。
34.typeid:指出指针或引用指向的对象的实际派生类型。
35.typename(类型名字)关键字告诉编译器把一个特殊的名字解释成一个类型。在下列情况下必须对一个 name 使用 typename 关键字:
- 一个唯一的name(可以作为类型理解),它嵌套在另一个类型中的。
- 依赖于一个模板参数,就是说:模板参数在某种程度上包含这个name。当模板参数使编译器在指认一个类型时产生了误解。
36.using:表明使用 namespace
37.virtual(虚的):C++ 中用来实现多态机制。
38.wchar_t :是宽字符类型,每个 wchar_t 类型占 2 个字节,16 位宽。汉字的表示就要用到 wchar_t。
39.char(字符,character)类型,C++ 中的基本数据结构,其值一般为 0~255 的 int。这 256 个字符对应着 256 个 ASCII 码。char 类型的数据需要用单引号 ' 括起来。
40.float(浮点数),C++ 中的基本数据结构,精度小于 double。
41.double(双精度)类型,C++ 中的基本数据结构,以双精度形式存储一个浮点数。
42.int(整型,integer),C++ 中的基本数据结构,用于表示整数,精度小于 long。
43.long(长整型,long integer),C++ 中的基本数据结构,用于表示长整数。
44.short(短整型,short integer),C++ 中的基本数据结构,用于表示整数,精度小于 int。
45.true(真的),C++ 的基本数据结构 bool 类型的值之一。等同于 int 的非 0 值。
46.void(空的),可以作为函数返回值,表明不返回任何数据;可以作为参数,表明没有参数传入(C++中不是必须的);可以作为指针使用。