static
- static 申明的变量为静态全局变量,该变量存储在静态数据区,当整个程序结束时该变量才会被释放,只是生命周期延长,作用域不受影响。
- static申明的变量定义时如果不初始化默认初始化为0
- 被static修饰的变量只能作用于本文件内,即使被extern修饰也不行
- 在 C 中 static 用来修饰局部静态变量和外部静态变量、函数。而 C++中除了上述功能外,还用来定义类的成员变量和函数。即静态成员和静态成员函数。
extern
- extern 标识的变量或者函数声明其定义在别的文件中,提示编译器遇到此变量和函数时在其它模块中寻找其定义。
inline
- 频繁使用的短小函数,c用宏定义,c++用inline
explicit
- 防止单参数的构造函数隐式类型转换,如果没有加explicit,可以把一个常量赋值给对象。
mutable
- 被mutable修饰的变量是可变的,即使是const类型,也可以修改。
volatile
- 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。
-
精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
下面是volatile变量的几个例子:
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3). 多线程应用中被几个任务共享的变量
define、const
- const修饰的变量为只读变量,定义一个const类型的变量时必须完成初始化 。
- define意为宏定义一个常量,给某个命名变量宏定义一个确定的数值,在预编译期间将会完成一个替换的动作。
- const也可以修饰函数的参数列表以及函数的返回值,参数返回值被const修饰代表参数和返回值均不能被改变。
- const修饰的变量可以通过强制类型转换转为非const(用const_cast)
- 被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
- const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
- 有些集成化的调试工具可以对const 常量进行调试,但是不能对宏常量进行调试。
define、typedef
| define | typedef | |
| 用法 | 定义常量 | 定义数据类型的别名 |
| 执行时间 | 预编译,字符串替换 | 编译过程,有类型检查 |
| 作用域 | 不受作用域约束 | 有作用域约束 |
| 不是语句,不加分号 | 是语句,要加分号 |
define/ifndef/endif
- 防止该头文件被重复引用
sizeof、strlen
| sizeof | strlen |
| 操作符、可重载 | 库函数、不可重载 |
| 参数可以是数据类型和变量 | 参数是字符串 |
| 表示占内存大小 | 表示字符串长度 |
| 编译时计算 | 运行时计算 |
strcpy、memcpy、sprintf
| strcpy | sprintf | memcpy | |
| 操作对象 | 字符串 |
源可以是多种数据类型 目的是字符串 |
可操作的内存地址 |
| 执行效率 | 中 | 低 | 高 |
| 功能 | 字符串变量间拷贝 | 其他数据类型到字符串 | 内存块间的拷贝 |
new/delete、malloc/free
| new/delete | malloc/free |
| 运算符(可重载) | 库函数(需要头文件) |
| 会调用构造析构函数 | 不会调用构造析构函数 |
| 有类型检查,返回相应类型 | 需要类型强制变换,默认返回void* |
| 指明对象类型和数量 | 指明申请空间大小 |
operator new、new operator、placement new
| operator new | 语言内建,不可以重载 |
| new operator | 操作符,可以重载(同时成对重载operator delete) |
| placement new | 希望手动管理内存时使用 |
delete[]怎么知道size的
对于复杂数据结构,
- new[]先调用operator new[]分配内存,
- 然后在p的前四个字节写入数组大小n,
- 然后调用n次构造函数。
假设指针p指向new[]分配的内存。
因为要4字节存储数组大小,实际分配的内存地址为[p-4],
系统记录的也是这个地址。
delete[]实际释放的就是p-4指向的内存。而delete会直接释放p指向的内存,
这个内存根本没有被系统记录,所以会崩溃。
static_cast、const_cast、dynamic cast、reinterpret_cast
| static_cast |
主要用于内置数据类型间的转换 用于自定义类时,会先判断类型之间的关系,没有关系则不可以转换 |
| const_cast |
常量 被强转为 非常量 |
| dynamic cast |
运行时处理的,要进行类型检查,其他都是编译时完成的 基类中一定要有虚函数,否则编译不通过
|
| reinterpret_cast | 不同类型的指针之间的强制转换 |
scope、shared、weak 智能指针
|
boost::scope_ptr boost::scope_array |
boost::shared_ptr boost::shared_array |
boost::weak_ptr | |
| 所有权 | 独享 | 共享 | 为shared_ptr准备的,只关心能否使用对象,不关心具体计数。 |
| 管理对象 |
ptr:单个堆 array:动态数组 |
ptr:单个堆 array:动态数组 |
|
| 操作 | 不可以复制、赋值 |
可以复制、赋值 用count计数实现 |
可以在基类中定义一个 boost::weak_ptr,用于指向子类的 boost::shared_ptr,
这样基类仅仅观察自己的 boost::weak_ptr 是否为空就知道子类有没对自己赋值了,
而不用影响子类 boost::shared_ptr 的引用计数,用以降低复杂度,更好的管理对象。
堆和栈
| 栈stack | 堆heap | |
| 内容 | 局部变量 | 动态分配变量 |
| 管理 | 编译器自动管理 | 程序员malloc/free控制 |
| 大小 | 通常很小 | 通常很大 |
| 碎片 | 无碎片 | 有外部碎片 |
| 效率 |
机器系统提供的数据结构 压栈出栈都有相关指令 效率很高 |
由C++函数库提供 效率较低 |
switch、多重ifelse
- switch语句只能处理等值条件判断的情况,而且条件只能是整型变量或字符型变量。
- 多重if选择结构的限制,特别适合某个变量处于某个连续区间时的情况
- switch case 当case是某个值的时候会直接把流程执行到那里,只进行一次判断。
- 而多重else if,else if的层次越深,需要判断的次数就越深。
- if else里面进行条件判断,比较灵活,switch case是一个常量的等值判断,灵活性没那么好,但是对于大范围的条件判断效率较高。
声明和定义
- 为变量分配地址和存储空间的称为定义,
- 不分配地址的称为声明。一个变量可以在多个地方声明,但是只在一个地方定义。
- 加入 extern 修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义。
往后再慢慢补充。