When you build and run the refCount project, you should get the following output in a console window:
dm1: refCount(pDom ++) = 1 dm2: refCount(pRoot ++) = 1 dm3: refCount(pElem ++) = 1 dm4: refCount(pElemOut ++) = 2 dm5: refCount(pElemA ++) = 3 dm6: refCount(pElem --) = 2 dm7: refCount(pElemOut --) = 1 dm8: refCount(pElemA ) = 1 dm9: refCount(pElem ++) = 1 dm10: refCount(pElemOut ++) = 2 dm11: refCount(pElemA --) = 0 dm12: refCount(pElem --) = 1 dm13: refCount(pElemOut --) = 0 dm14: refCount(pElem ++) = 1 dm15: refCount(pElemOut ++) = 2 dm16: refCount(pElem --) = 1 dm17: refCount(pElemOut --) = 0 dm18: refCount(pElemOut ++) = 2 dm19: refCount(pElemOut --) = 1 pDom->xml: <root><A><a>11</a></A><B>2</B></root> dm20: refCount(pDom --) = 0 dm21: refCount(pRoot --) = 0
The following remarks explain the various reference counts shown above. However, because reference counting is implementation-dependent, these discussions might or might not apply to other objects.
pDom, which corresponds to the document element; pRoot, which corresponds to the <root> element; and pElem, which corresponds to the <A> element. Because these objects are new and distinct, the reference count equals 1 on each interface pointer. pElemOut as returned from the call to pRoot->appendChild method. Because pElemOut is another reference to the pElem object, when the call succeeds its reference count is 1 plus the count on pElemthat is, 2.pElemA, which is a copy of pElemOut; pElemA is used to hold the <A> element, so that pElem and pElemOut can be recycled to represent other elements. So far, pElem, pElemOut, and pElemA all point to the same object. Therefore, the reference count on pElemA is 3. pElem, pElemOut, and pElemA after the Release method has been called on pElem and pElemOut. These two interface pointers need to be released, because they will be used to add another element, <a>, to the XML document. Remember that at this point in the code all three interface pointers still reference the same object. This means that the reference counts on them are correlated with each other. Failure to release pElem or pElemOut here will result in a memory leak. pElem interface pointer, which points to a newly created IXMLDOMNode object. This object, which represents the <a> element, is to be added as a child of <A>. Because this is a newly created object, the reference count on this interface pointer is 1.pElemOut as returned from the call to pElemA->appendChild method. This element is another reference to the pElem object, <a>. Therefore, when the call succeeds, its reference count is 1 plus the reference count on pElemthat is, 2.pElemA, pElem, and pElemOut after the Release method was called on each of the interface pointers. The system has released pElemA because we are done with <A>; when the reference count on pElemA reaches zero, the system frees the memory object pointed to by the pElemA interface pointer. Any attempt to access this object will result in access violation. The other two interface pointers are released because we are ready to move on to the next element, <B>. Failing to release pElem and pElemOut here would result in a memory leak.pElem interface pointer, which points to a newly created IXMLDOMNode object, <B>. This object is to be added as a child of <root>. Because pElem is not a copy of another interface pointer, the reference count is 1.pElemOut as returned from the call to pRoot->appendChild method. This element is another reference to the pElem object, <B>. Therefore, when the call succeeds, its reference count is 1 plus the reference count on pElemthat is, 2.pElem and pElemOut after the Release method was called on each of the interface pointers. These two interface pointers are released because we are done with <B>. Failing to release pElemOut here would result in memory leak.pElemOut as returned from the call to pDom->appendChild method. This element is another reference to the pRoot object, <root>. Therefore, when the call succeeds, its reference count is 1 plus the reference count on pRootthat is, 2.pElemOut, pDom, and pRoot after the Release method has been called on each of the interface pointers. These interface pointers are released because they are no longer needed. All the memory objects allocated in this application are freed when the application ends.