undefined

基本概念

1
2
3
4
5
C++标准里一个相关概念是自由存储区(free store),特指使用new 和 delete 来分配和释放内存的区域。一般而言,这是堆的一个子集。
new 和 delete 操作的区域是 free store
malloc 和 free 操作的区域是 heap

RAII:Resource Acquisition Is Initialization. 是C++所特有的资源管理方式。

栈展开

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
编译器会自动调用析构函数,包括在函数执行发生异常的情况。在发送异常时对析构函数的调用,专门的术语叫“栈展开”。如下面代码:

class Obj {
public:
Obj() { puts("Obj()"); }
~Obj() { puts("~Obj()"); }
};

void foo(int n) {
Obj obj;
if (n == 42)
throw "life, the universe and everything";
}

int main() {
try {
foo(41);
foo(41);
} catch (const char* s) {
puts(s);
}
}
执行代码的结果是:
Obj()
~Obj()
Obj()
~Obj()
life, the universe and everything

不管是否发送了异常,obj 的析构函数都会得到执行

RAII

1
2
3
4
5
6
7
8
9
10
C++有时候不应该讲对象存储在栈上,比如
1. 对象很大
2. 对象的大小在编译时不能确定
3. 对象时函数的返回值,但由于特殊原因,不应使用对象的值返回

在析构函数中做必要的清理工作,这就是RAII的基本用法,这种清理并不限于释放内存。也可以是:
1. 关闭文件(fstram的析构就会这么做)
2. 释放同步锁
3. 释放其他重要的系统资源
智能指针就是 RAII 思想的体现

对象切片的现象

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
enum class shape_type {
circle,
triangle,
rectangle,
...
};

class shape { ... };
class circle : public shape { ... };
class triangle : public shape { ... };
class rectangle : public shape { ... };

shape* create_shape(shape_type type) {
...
switch (type) {
case shape_type::circle:
return new circle(...);
case shape_type::triangle:
return new triangle(...);
case shape_type::rectangle:
return new rectangle(...);
...
}
}

如上这种情况,只能返回指针或其他变体。如果返回类型是 shape,实际却返回一个 circle,编译器不会报错,但结果多半是错的。这种现象就是对象切片(object slicing),这种错误不是语法错误,而是一个对象复制相关的语义错误。