getter_doesnt_AddRef
is gone (Re: nsCOMPtr
questions)
Document Status: Retired.
This document is now obsolete.
Coincidentally, as of 25 October 1999, the information in it is still accurate.
However, please use the
nsCOMPtr
User's Manual
as your reference.
getter_AddRefs
,
the now illegal getter_doesnt_AddRef
,
and some esoterica about services.
There is a followup message.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 |getter_doesnt_AddRef| no longer exists. It no longer exists because it is a rule of COM (and hence XPCOM) that all `getter' functions _must_ AddRef the interface pointer they produce before returning it. A getter is any function that yields a COM interface pointer (either as it's actual result or through a parameter). The prototypical case is: class Foo { public: nsresult GetX( X** ); // a `getter' (in the standard form) // nsresult SetX( X* ); // a `setter' X* GetX(); // a non-standard getter private: X* mX; }; Note also that by this definition factory functions are also getters. |nsComponentManager::CreateInstance| is a (factory function style) `getter'. Normally, when you assign a COM interface pointer into an |nsCOMPtr| variable, the |nsCOMPtr| is responsible for |AddRef|ing the interface. However, like all good `getter's, |nsComponentManager::CreateInstance| |AddRef|s its result (the created component), therefore, when giving it an |nsCOMPtr| argument to store that result in, you must tell the |nsCOMPtr| that the getter function (CreateInstance, here) will do the |AddRef|, not the |nsCOMPtr| itself. Here are some examples: X* aRawX; nsresult CreateAnX( X** result ); X* CreateAnX(); // Note, like all `getters' |CreateAnX()| // |AddRef|s its result (in both forms) nsCOMPtr<X> x1 = aRawX; // An |nsCOMPtr| automatically |AddRef|s // when you assign into it. // That's good, here. nsCOMPtr<X> x2 = CreateAnX(); // Oops! the |nsCOMPtr| automatically // |AddRef|s, _and_ |CreateAnX()| |AddRef|s // Leak!! nsCOMPtr<X> x3 = getter_AddRefs( CreateAnX() ); // Tell the |nsCOMPtr| _not_ to |AddRef|, // Now only |CreateAnX()| |AddRef|s // No more Leak nsCOMPtr<X> x4; nsresult status = CreateAnX( getter_AddRefs(x4) ); // |CreateAnX()| will assign into |x4|, // so tell |x4| _not_ to |AddRef| // since |CreateAnX()| already calls |AddRef| This makes the answer easy for your _component_ statement: nsCOMPtr<nsIDataFlavor> flavor; nsresult rv = nsComponentManager::CreateInstance(kCDataFlavorCID, 0, kIDataFlavorIID, getter_AddRefs(flavor)); I use a template function (that I have not checked in yet) to make this scenario simpler. This is the function: template <class T> inline nsresult CreateComponent( const nsCID& cid, nsCOMPtr<T>* created_component, nsISupports* delegate = 0 ) { assert(created_component); return nsComponentManager::CreateInstance(cid, delegate, T::GetIID(), getter_AddRefs(*created_component)); } This reduces the code you would write to: nsCOMPtr<nsIDataFlavor> flavor; nsresult rv = CreateComponent(kCDataFlavorCID, &flavor); The problem with services, however, is that you don't |AddRef| and |Release| them. For that reason, you wouldn't, at least currently, want to use an |nsCOMPtr| to manage |AddRef|s and |Release|s on them. You acquire an interest in a service with |GetService|, and release that interest with |ReleaseService|. |AddRef| and |Release| don't come into it. Unless this changes, don't use |nsCOMPtr|s to hold references to services. Hope this helps, ______________________________________________________________________ Scott Collins <http://www.meer.net/ScottCollins?Netscape> -----BEGIN PGP SIGNATURE----- Version: PGP Personal Privacy 6.0.2 Comment: get my key at <http://www.meer.net/ScottCollins/#key> iQA/AwUBNx9mEvGmojMuVn+fEQJSagCgqDlafzoK5kSE29iNJ5ubED1/qHQAoL/T ZVq0h8RqfWo3Zmcys37uT6PQ =w15I -----END PGP SIGNATURE-----