在计算机程序设计中，**弱引用**与强引用相对，是指不能确保其引用的对象不会被垃圾回收器回收的引用。一个对象若只被弱引用所引用，则被认为是不可访问（或弱可访问）的，并因此可能在任何时刻被回收。一些配有垃圾回收机制的语言，如Java、C#、Python、Perl、Lisp等都在不同程度上支持弱引用。

垃圾回收
----

条目：垃圾回收 (计算机科学)
垃圾回收用来清理不会再使用的对象，从而降低内存泄露和数据损坏的可能性。垃圾回收主要有两种类型：追踪和引用计数。引用计数会记录给定对象的引用个数，并在引用个数为零时收集该对象。由于一次仅能有一个对象被回收，引用计数无法回收循环引用的对象。一组相互引用的对象若没有被其它对象直接引用，并且不可访问，则会永久存活下来。一个应用程序如果持续地产生这种不可访问的对象群组，就会发生内存泄漏。在对象群组内部使用弱引用（即不会在引用计数中被计数的引用）有时能避免出现引用环，因此弱引用可用于解决循环引用的问题。如Apple的Cocoa框架就推荐使用这种方法，具体为，在父对子引用时使用强引用，子对父引用时使用弱引用，从而避免了循环引用。 （页面存档备份，存于）

程序对一些对象只进行弱引用，通过此法可以指明哪些对象是不重要的，因此弱引用也用于尽量减少内存中不必要的对象存在的数量。

变种
--

有些语言包含多种强度的弱引用。例如Java，在java.lang.ref包中定义了软引用、弱引用和虚引用，引用强度依次递减。每种引用都有相对应的可访问性概念。垃圾回收器（GC）通过判断对象的可访问性类型来确定何时回收该对象。当一个对象是软可访问的，垃圾回收器就可以安全回收这个对象，但如果垃圾回收器认为JVM还能空出可用内存（比如JVM还有大量未使用的堆空间），则有可能不会立刻回收软可访问的对象。但对于弱可访问的对象，一旦被垃圾回收器注意到，就会被回收。和其他引用种类不同，虚引用无法跟踪。但另一方面，虚引用提供了一种机制，当一个对象被回收时程序可以得到通知（实现于ReferenceQueues）。 
一些未配有垃圾回收机制的语言，比如C++，也提供强/弱引用的功能，以作为对垃圾回收库的支持。在C++中，普通指针可看做弱引用，智能指针可看做强引用，尽管指针不能算"真正"的弱引用，因为弱引用应该能知道何时对象变成不可访问的了。

示例
--

弱引用可用于在应用程序中维护一个当前被引用的对象的列表。该列表必须弱引用到那些对象，否则一旦对象被添加到列表中，由于它们被列表引用了，在程序运行期间将永远不会被回收。

### Java

Java是第一个将强引用作为默认对象引用的主流语言。之前的（ANSI）C语言只支持弱引用。而后David Hostettler Wain和Scott Alexander Nesmith注意到事件树无法正常释放的问题，结果在大约1998年，推出了分别会被计数和不会被计数的强、弱引用。 
如果创建了一个弱引用，然后在代码的其它地方用 `get()`获得真实对象，由于弱引用无法阻止垃圾回收，`get()`随时有可能开始返回 `null`（假如对象没有被强引用）。

```
import java.lang.ref.WeakReference;
 
public class ReferenceTest {
 public static void main(String[] args) throws InterruptedException {
 
 WeakReference r = new WeakReference(new String("I'm here"));
 WeakReference sr = new WeakReference("I'm here");
 System.out.println("before gc: r=" + r.get() + ", static=" + sr.get());
 System.gc();
 Thread.sleep(100);
 
 //只有r.get()变为null
 System.out.println("after gc: r=" + r.get() + ", static=" + sr.get());
 
 }
}

```

弱引用还可以用来实现缓存。例如用弱哈希表，即通过弱引用来缓存各种引用对象的哈希表。当垃圾回收器运行时，假如应用程序的内存占用量高到一定程度，那些不再被其它对象所引用的缓存对象就会被自动释放。

### Smalltalk

```
|a s1 s2|

s1 := 'hello' copy. "这是个强引用"
s2 := 'world' copy. "这是个强引用"
a := WeakArray with:s1 with:s2.
a printOn: Transcript. 
ObjectMemory collectGarbage.
a printOn: Transcript. "两个元素都还在"

s1 := nil. "移除强引用" 
ObjectMemory collectGarbage.
a printOn: Transcript. "第一个元素消失"

s2 := nil. "移除强引用" 
ObjectMemory collectGarbage.
a printOn: Transcript. "第二个元素消失"

```

### Lua

```
weak\_table = setmetatable({}, {\_\_mode="v"})
weak\_table.item = {}
print(weak\_table.item)
collectgarbage()
print(weak\_table.item)

```

### Objective-C 2.0

在Objective-C 2.0中，除了垃圾回收，自动引用计数也会受弱引用的影响。下面这个例子中的所有变量和属性都是弱引用。

```
@interface WeakRef : NSObject
{
 \_\_weak NSString \*str1;
 \_\_assign NSString \*str2;
}
 
@property (nonatomic, weak) NSString \*str3;
@property (nonatomic, assign) NSString \*str4;
 
@end

```

`weak`(`__weak`)和`assign`(`__assign`)的区别在于，当变量指向的对象被重新分配时，变量的值是否会跟着改变。`weak`声明的变量会变为`nil`，而`assign`声明的变量则会保持不变，成为一个悬摆指针。从Mac OX 10.7 "狮子"系统和iOS 5开始，随着Xcode 4.1版本的推出，`weak`引用被引入到Objective-C语言中（4.2版本开始支持iOS）。老版本的Mac OS X、iOS和GNUstep仅支持用`assign`声明弱引用。

### Vala

```
class Node {
 public weak Node prev; //弱引用可避免列表中的节点之间出现循环引用
 public Node next;
}

```

### Python

```
>>> import weakref
>>> import gc
>>> class Egg:
...     def spam(self):
...         print("I'm alive!")
...
>>> obj = Egg()
>>> weak\_obj = weakref.ref(obj)
>>> weak\_obj().spam()
I'm alive!
>>> obj = "Something else"
>>> gc.collect()
35
>>> weak\_obj().spam()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'spam'

```

参考文献
----

1. ↑ .  [2013-12-28]. （原始内容存档于2022-06-06）.
2. ↑  Nicholas, Ethan. "Understanding Weak References" 的存檔，存档日期2010-08-19.. java.net （页面存档备份，存于）. 发布于2006年5月4日. 访问于2010年10月1日
3. ↑ .  [2013-12-28]. （原始内容存档于2011-09-30）.
4. ↑  weblogs.java.net Java Examples  的存檔，存档日期2010-08-19.

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
記憶體管理 |
| --- |
|  |
| 
* 操作系统的内存管理功能（英语：）

 |
|  |
| 手动内存管理（英语：） | 
* 静态内存分配
* C动态内存分配
* new (C++)
* delete (C++)（英语：）

 |
|  |
| 虚拟内存 | 
* 按需分页（英语：）
* 分頁表
* 分頁
* 虚拟内存压缩（英语：）

 |
|  |
| 硬件内存管理 | 
* 内存管理单元
* 轉譯後備緩衝區

 |
|  |
| 垃圾回收 | 
* 貝姆垃圾收集器
* Cheney算法
* 终止器（英语：）
* 垃圾（英语：）
* 标记压缩算法（英语：）
* 引用计数
* 强引用
* 弱引用
* 追踪垃圾回收

 |
|  |
| 記憶體分段 | 
* 保護模式
* 真實模式
* 虚拟8086模式
* X86記憶體區段

 |
|  |
| 記憶體安全 | 
* 缓冲区溢出
* 缓冲区过读
* 迷途指针
* 堆疊溢位

 |
|  |
| 针对的问题 | 
* 内存碎片化
* 内存泄漏
* 不可访问内存

 |
|  |
| 其它 | 
* 自动变量
* 内存管理国际研讨会（英语：）
* 基于区域内存管理（英语：）

 |

 |