RefPtr

RefPtr (formerly known as nsRefPtr, see bug 1207245) is a general class to implement reference counting pointers for objects. It is similar to nsCOMPtr, but does not require that the type be an XPCOM interface. Like with nsCOMPtr, it is the responsibility of the object itself to implement reference counting. This is done using the functions AddRef() and Release(), which respectively modify a variable of type nsAutoRefCnt, which basically is a wrapper around a count of the number of references refering to the class.

When should I use nsCOMPtr versus RefPtr?

The rules are simple: use nsCOMPtr to hold pointers to XPCOM interfaces, and use RefPtr to hold pointers to concrete class, even if the concrete class implements one or more XPCOM interfaces.

So for XPCOM interfaces:

nsCOMPtr<nsISupports> a;

nsCOMPtr<nsIFoo> foo;

And for concrete classes:

RefPtr<nsFoo> foo;  // class that implements nsIFoo;

RefPtr<Bar> bar;    // some random class that I want ref-counted but has nothing to do with XPCOM:
                    // Just implement AddRef() and Release() and it will work with RefPtr

It is important that nsCOMPtr is not used to hold a pointer to a concrete class since this can cause compile time errors or runtime errors. Bug 756640 is on file to enforce this rule but hasn't yet been fixed.

While RefPtr should not generally be used to hold a pointer to an XPCOM interface, this is flexible. There are no technical problems with doing so, and in some cases it may be necessary (see bug 756640 comment 1). For example, we have template classes such as OwningNullPtr that can contain a RefPtr to an XPCOM interface.

XXX It's not clear that the details in the following paragraph are correct. It was derived from an old #developers discussion. It's unclear to me when the compiler will reject an attempt to use nsCOMPtr to hold a concrete class pointer and when it will not (will it only rejecte it if a QI is involved in the construction or or assignment to the nsCOMPtr (common in implementation details of nsCOMPtr) but not when an instance of the concrete class is assigned directly?). And it's not clear what happens when the compiler does accept this pattern. What goes wrong at runtime - UAF? memory leak? QI failure and null-deref crashes?.

Note: in the above example, "nsCOMPtr<nsFoo>" might compile and work OK (it won't if your XPCOM class multiply-inherits nsISupports). But this is considered Bad Form, and may soon be made a compile-time error. Don't do it!

Can I QueryInterface a RefPtr to get a nsCOMPtr from the object it points to?

Sure. Instead of using "do_QueryInterface()" (which is used for nsCOMPtrs), use "do_QueryObject()", which works with RefPtrs:

// Let's say nsFoo implements nsIFoo and nsIBar XPCOM interfaces:
RefPtr<nsFoo> foo = new nsFoo();
nsCOMPtr<nsIBar> bar(do_QueryObject(foo));
MOZ_ASSERT(bar, "Yikes someone changed the base classes of nsFoo");

Can I QueryInterface an nsCOMPtr back to a RefPtr?

Yes. If the concrete class has its own XPCOM IID (not true by default, but one can be added), you can also QI from an XPCOM pointer to a concrete type:

bar = do_QueryObject(foo);
if (bar) { ... }

See this post for more details.