, SteveRichter wrote

I thought the lesson learned by the designers of the GC was that reference counting was slower than garbage collecting. 

Reference counting is orders of magnitude faster than performing a GC.

The reason .NET and other managed languages choose a GC is it detects circular references.

Consider a linkedlist with reference counting:

func main()

LinkedListNode i = new LLNode();
// ref count of i = 1
LinkedListNode j = new LLNode();
// ref count of j = 1
i->Flink = j;
// ref count of i = 2
j->Blink = i;
// ref count of j = 2

i = nullptr;
// ref count of i = 1
j = nullptr
// ref count of j = 1


So now we've leaked i and j. Nobody points to them, but their ref-count is 1 (and hence won't be deleted) since i points to j and j points to i.

GC solves this problem by saying that both i and j are not reachable at the end of main, and hence are eligible for collection.