# 垃圾回收(应用程序二进制接口)
在C++中,垃圾回收机制(自动回收没有被引用的内存区域)是可选的;也就是说在编译器中并不是一定要实现垃圾回收器。尽管如此,C++0x还是定义了垃圾回收器的功能。与此同时,C++0x还提供了应用程序二进制接口(ABI: Application Binary Interface)来辅助控制垃圾回收器的行为。
我们用“safely derived pointer”(3.7.3.3)(译注:我搜索后发现,是在3.7.3.3而不是3.7.4.3讲了safely derived pointer。这里可能是原文作者的笔误)来表示指针和生存时间的规则;粗略地说就是 “指向由new分配的对象或者指向相应的子对象的指针”。 下面是一些关于“not safely derived pointers”又名“disguised pointers”,或者说是为便于正常人理解和认可你的程序从而你应该注意的一些问题。
* 将指针暂时指到别处:
```
int* p = new int;
p+=10;
//…垃圾回收器可能在这里运行…
p-=10;
//在此,我们是否可以肯定开始为p分配的那块int内存还存在?
*p = 10;
```
* 将指针隐藏到一个int变量中:
```
int* p = new int;
int x = reinterpret_cast(p); // non-portable (不可移植)
p=0;
//…垃圾回收器可能在这里运行…
p = reinterpret_cast(x);
//在此,我们是否可以肯定开始为p分配的那块int内存还存在?
*p = 10;
```
* 还有更多甚至更危险的陷阱。比如I/O,以及将存储不同的数据位打散,..
虽然我们也有一些合理的理由来伪装指针(例如:xor有可能在exceptionally memory-constrained applications中导致错误),但是理由并不像一些程序员所认为的那么多。
程序员可以在代码中声明哪些地方不会有指针被发现(比如在一个图像中),也可以声明哪些内存区域不能被回收,即使垃圾回收器发现没有任何指针指向这块内存区域。以下是相关的例子:
void declare_reachable(void* p); //以p起始的内存区域
//(用能够记住所分配内存区域大小
//的内存分配操作符分配)不能被回收
```
template<class T> T* undeclared_reachable(T* p);
void declare_no_pointers(char* p, size_t n); //p[0..n] 中没有指针
void undeclared_no_poitners(char* p, size_t n);
```
程序员要能够查询到关于指针安全和回收的规则是否是强制性的:
```
enum class pointer_saftety {relaxed, preferred, strict};
pointer_safety get_pointer_safety();
```
3.7.4.3[4]:满足以下三个条件的行为没有被定义:如果一个非”safely-derived pointer”值被释放,并且它所引用的对象是动态存储期(由new操作符动态创建并由delete销毁的对象拥有动态存储期),与此同时这个指针之前也没被声明为可到达的(20.7.13.7)。
* relaxed: safely-derived pointer和not safely-derived pointer被认为是等同的。这和C以及C++98中是一样的。但这并不是我的初衷。我的想法是用户如果没有使用有效的指针指向一个对象则应启用垃圾回收。
* Preferred:和relaxed类型一样。只不过垃圾回收器可能被用作内存泄露检测以及(或者)检测对象是否被一个错误的指针解引用。
* strict: safely-derived和not safely-derive这两种指针可能不再被等同。也就是说,垃圾回收器可能被启用而且将会忽略那些not safely derived pointer。
并不存在任何标准化的方法以供你选择任何一种。这是一个实现的质量(quality of implementation)和编程环境(programming environment)的问题。
另外,可以参考以下文献:
* the C++ draft 3.7.4.3
* the C++ draft 20.7.13.7
* Hans Boehm’s
[GC page](http://www.hpl.hp.com/personal/Hans_Boehm/gc/)
* Hans Boehm’s
[Discussion of Conservative GC](http://www.hpl.hp.com/personal/Hans_Boehm/gc/issues.html)
* [final proposal](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2527.pdf)
* Michael Spertus and Hans J. Boehm:
[The Status of Garbage Collection in C++0X](http://portal.acm.org/citation.cfm?doid=1542431.1542437)
.
ACM ISMM’09.
(翻译:Yibo Zhu)
- C++11 FAQ中文版 - C++11 FAQ
- Stroustrup先生关于中文版的授权许可邮件
- Stroustrup先生关于C++11 FAQ的一些说明
- 关于C++11的一般性的问题
- 您是如何看待C++11的?
- 什么时候C++0x会成为一部正式的标准呢?
- 编译器何时将会实现C++11标准呢?
- 我们何时可以用到新的标准库文件?
- C++0x将提供何种新的语言特性呢?
- C++11会提供哪些新的标准库文件呢?
- C++0x努力要达到的目标有哪些?
- 指导标准委员会的具体设计目标是什么?
- 在哪里可以找到标准委员会的报告?
- 从哪里可以获得有关C++11的学术性和技术性的参考资料?
- 还有哪些地方我可以读到关于 C++0x的资料?
- 有关于C++11的视频吗?
- C++0x难学吗?
- 标准委员会是如何运行的?
- 谁在标准委员会里?
- 实现者应以什么顺序提供C++11特性?
- 将会是C++1x吗?
- 标准中的"concepts"怎么了?
- 有你不喜欢的C++特性吗?
- 关于独立的语言特性的问题
- __cplusplus宏
- alignment(对齐方式)
- 属性(Attributes)
- atomic_operations
- auto – 从初始化中推断数据类型
- C99功能特性
- 枚举类——具有类域和强类型的枚举
- carries_dependency
- 复制和重新抛出异常
- 常量表达式(constexpr)
- decltype – 推断表达式的数据类型
- 控制默认函数——默认或者禁用
- 控制默认函数——移动(move)或者复制(copy)
- 委托构造函数(Delegating constructors)
- 并发性动态初始化和析构
- noexcept – 阻止异常的传播与扩散
- 显式转换操作符
- 扩展整型
- 外部模板声明
- 序列for循环语句
- 返回值类型后置语法
- 类成员的内部初始化
- 继承的构造函数
- 初始化列表
- 内联命名空间
- Lambda表达式
- 用作模板参数的局部类型
- long long(长长整数类型)
- 内存模型
- 预防窄转换
- nullptr——空指针标识
- 对重载(override)的控制: override
- 对重载(override)的控制:final
- POD
- 原生字符串标识
- 右角括号
- 右值引用
- Simple SFINAE rule
- 静态(编译期)断言 — static_assert
- 模板别名(正式的名称为"template typedef")
- 线程本地化存储 (thread_local)
- unicode字符
- 统一初始化的语法和语义
- (广义的)联合体
- 用户定义数据标识(User-defined literals)
- 可变参数模板(Variadic Templates)
- 关于标准库的问题
- abandoning_a_process
- 算法方面的改进
- array
- async()
- atomic_operations
- 条件变量(Condition variables)
- 标准库中容器方面的改进
- std::function 和 std::bind
- std::forward_list
- std::future和std::promise
- 垃圾回收(应用程序二进制接口)
- 无序容器(unordered containers)
- 锁(locks)
- metaprogramming(元编程)and type traits
- 互斥
- 随机数的产生
- 正则表达式(regular expressions)
- 具有作用域的内存分配器
- 共享资源的智能指针——shared_ptr
- smart pointers
- 线程(thread)
- 时间工具程序
- 标准库中的元组(std::tuple)
- unique_ptr
- weak_ptr
- system error