C++ Basic (3)
1. Scope and Lifespan of Variable
- 全局变量: 所有源代码, 程序运行结束时销毁
- 全局静态变量: 单个源文件, 程序运行结束时销毁
- 局部变量: 所在函数, 函数运行完毕时销毁
- 静态局部变量: 所在函数, 但会在调用函数前初始化, 程序运行结束时销毁
- 静态成员变量: 所在class内, 所有对象共享该成员, 因此该成员会在生成对象前初始化, 程序运行结束时销毁
2. const and #define
相比于define, 使用const有以下好处:
- const会检查数据类型, define不会
- const效率更高. const定义的常量不会保存在内存中, 而是在符号表(symbol table)中, 每次访问const数据不必从内存中读取和存储, 因此效率高
3. struct in C++
C++的struct与C的struct完全不同, C++中的struct十分接近class, 其具备继承(inheritance)和多态(polymorphism), 但无法设置访问权限.
struct A { |
4. SOLID Principles in OOP
- SRP(Single-Resposibility Principle, 单一职责原则): 每个模块, 类, 或函数只承担一个职责, 并且封装实现.
- OCP(Open-Close Principle, 开放封闭原则): 实体应该对拓展开放, 对修改封闭.
- LSP(Liskov Substituion Principle, 里式替换原则): 子类应能够替换它的基类. 例如, class B是class A的子类, 以class A为参数的函数也能接受class B的对象, 且不会导致任何异常, 这么做能保证子类继承了父类的一切.
- ISP(Interface Segregation Principle, 接口隔离原则): 保持接口的独立, 也就是说, 很多个客户端特定的接口, 优于一个多用途的接口.
- DIP(Dependecy Inversion Principle, 依赖倒置原则): class应依赖接口和抽象类, 而不是具体的class或函数.
5. Class Inheritance
class A { |
6. Initialization List
使用初始化列表可少调用一次default constructor,从而提高效率, 减少错误. 以下三种情况必须使用初始化列表:
- 成员所在的类没有默认构造函数
- const修饰的类成员或引用成员数据
- 子类初始化父类的私有成员
static成员变量不属于某个对象, 所以不能在constructor内初始化
7. Function Pointer
函数指针有两种方法: pf=f1
和pf=&f1
, 但必须保证参数类型和返回值类型匹配.
int f1(float); |
8. Object on the stack/heap
调用Class obj
不能保证类对象分配到栈中, 因为C++遵循自动存储(automatic storage), 会根据context决定存储位置.
- Object obj存储在栈中
void func(void){
Object obj; // 在函数中创建类对象会直接分配到栈中
} - Object obj存储在堆中
class Object2 {
Object obj;
}
Object2 *pObj2 = new Object2(); // 由于pObj2所指向的对象在堆上分配空间, 所以obj也在堆上分配空间 - Object Obj在静态存储区
Object obj; // 将obj存为全局变量
Stack与Heap上创建对象的区别:
- 性能
- heap上分配对象的时间为常量
- stack上分配对象的时间不定, 因为操作系统需追踪内存的可用区域
- 生存周期
- heap上对象的生存周期与上下文有关
- stack上的对象拥有更长的生存周期
9. private member in inheritance
父类的私有变量仍在子类的内存中, 但由于编译器的限制所以无法访问.
class A{ |
10. default value in arrray
int a[2][2] = {{1},{1,2}}; |
11. clone and fork
fork()
: 复制父进程的所有资源, 因此无需携带参数.clone()
: 复制父进程的部分资源, 复制哪些资源可通过参数设定, 所以clone()
携带参数, 没有复制的资源可以通过指针共享给子进程
12. abs()
- 输入为非负整数, 返回非负整数
- 输入为负数, 且不为最小负数, 返回其绝对值
- 输入为最小负数(
INT_MIN
), 还是返回最小负数
13. malloc and new
A *p1 = new A; // 调用了构造函数 |
14. Polymorphism
- 编译时多态性(override): 通过静态联编完成, 例如函数重载, 运算符重载
- 运行时多态性(overload): 通过动态联编完成, 主要通过虚函数来实现;
15. convert pointer to const
允许int*
转为const int*
, 但不允许转换多级指针(如int**
转为const int**
)
int x = 1; |
16. Value Assignment in For Loop
for (int i = 1; i = 0; ++i) {}; // 由于i为0, 逻辑为假, 不进入循环 |
17. Functions in Empty Class
以下是空类含有的函数:
- copy constructor
- copy assignment operator
- destructor
- default constructor
以上函数都是public且inline的
18. Initialize Two Dimensional Array
a[2][3] = {1, 2, 3}; // OK, a[2][3]={{1,2,3},{0,0,0}} |
19. Zero Argument Constructor
无参构造函数创建对象时, 不应该在对象名后加括号
A a(); // error, 这样会声明一个名为a的函数 |
20. Sequence Point
int a = (0, 1); |
逗号表达式是一组由逗号分隔的表达式, 从左向右计算, 结果为表达式最右边的值; 若最后边的操作数是左值, 则逗号表达式的值也是左值. 此类表达式通常用于for循环.
21. Order of Execution of Destructor
class A { |
22. cin >> unsigned integer
%u
/%o
/%x
代表10/8/16进制的无符号数%n
接受一个uint数, 代表到%n
之前所输入的字符数
23 order of struct member in memory
对于struct, 每个成员的内存从低到高依次排序.
struct mybitfields { |
对于class, 若没有交叉的access specifier(如private和public交叉使用), 则成员变量在内存上从低到高依次排序; 若存在交叉的access specifier, 则依据不同compiler的实现而定.
24. Initialization of Character Array
char s1[] = "abc"; |
25. Implicit Type Conversion
如果表达式中同时存在signed int和unsigned int, 会将signed int转换为unsigned int
int i = -1; |
26. Double Free and Bitwise Copy
默认copy constructor使用bitwise copy,
class A { |
27. Stack Memory Allocation
void* malloc(unsigned int size)
- 在stack中分配一段长度为size的连续空间
- 成功时返回首地址, 失败时返回NULL
- 不会初始化内存
void* calloc(unsigned int num, unsigned int size)
- 根据数据个数和数据类型所占字节数, 分配size*num大小的连续空间
- 成功时返回首地址, 失败时返回NULL
- 会自动初始化内存为0
void* realloc(void *ptr, unsigned int size)
- 分配一段长为size的内存空间, 并把内存空间的首地址赋值给ptr
- 内存分配失败则返回NULL
- 不会初始化内存
void* operator new (std::size_t size)
- 自动计算需要分配的内存空间大小, 并调用类的构造函数
- 成功时返回首地址, 失败时抛出bad_alloc异常
- 不对类中的内置类型变量进行初始化
28. Formatting String
printf("%s , %5.3s\n","computer","computer"); |
29. Base class pointer pointing to derived class object
class Base { |
30. condition of switch
switch
的condition应为integral(整数), enumeration(枚举), 或可以隐式转换为整数或整数的class. 整数有以下几种:
- short
- char
- int
- long
- bool
非整数类型包含float和double
31. Copy Constructor
声明copy constructor时需注意以下几点:
- 返回值的类型是否应为类型引用(否则无法连续赋值)
- 传入参数的类型是否应为引用(否则导致递归调用)
- 是否释放内存空间
- 是否判断传入参数和当前实例为同一实例
class A { |
32. Access Specifiers
- member declarations
- public:
- 类内: public和protected成员可访问
- 类外: 可在类外访问
- protected:
- 类内: public和protected成员可访问
- 类外: 不可访问
- private:
- 类内: public和protected成员可访问
- 类外: 不可访问
- public:
- base-specifier
- public: base class中public和protected的访问权限不变
- protected: base class中public变为protected, protected变为private
- private: base class中public和protected变为private