Advertisement

Are COM pointers released in the reverse order of their declaration?

Started by January 04, 2025 04:04 AM
3 comments, last by frob 6 days, 15 hours ago

For example, I have 4 COM pointers, named ptr0 to ptr3, and initialize them in the constructor as follows:

Class::Class()
{
	// Real code
	ptr3 = ...
	ptr2 = ...
	ptr0 = ...
	ptr1 = ...
}

Are they automatically released in the destructor in the reverse order of their declaration, like this? Like how a class would be destructed in the reverse order of its construction.

Class::~Class()
{
	// Not real code, just my assumption of what happens
	ptr1->Release();
	ptr0->Release();
	ptr2->Release();
	ptr3->Release();
}

I've been getting interested in RAII and other stuff like this now that I've had it explained to me in a way that I can clearly understand, but I want someone more qualified to make sure if my assumption of what happens in the above examples is correct or not, just so that I feel comfortable with what happens during my code and how I can control it.

Like how a class would be destructed in the reverse order of its construction.

Yes. The destruction order of class members is always the same (reverse), no matter what type you use. So the CComPtr-destructors will be called in exactly that same reverse order, internally releasing the references.

Advertisement

@Juliean Thank you! Now I'm actually comfortable with COM pointers and RAII.

Yup, you can call the functions in the order you want if you do it intentionally. You should be calling Release() at a time and order that makes sense, especially if the default ordering doesn't work for you.

The language specifies the order of destruction. The destructors for the objects also call Release() if you haven't released them yet, so release them in your preferred order explicitly is good.

Otherwise, the order is exactly the reverse of construction:

  • Your class destructor is called, running whatever you've got in it.
  • Nonstatic members are destroyed in the reverse order they appear in the declaration. Whatever order you've got them in the .h file they go from bottom to top.
  • Destructors for non-virtual base classes, in reverse order. If you derived from base class A and base class B, they'll be destroyed in order B then A.
  • Finally, virtual base class destructors are called, in reverse order. Not used often, but important as the diamond inheritance pattern both creates and solves various problems in design.

So if your header has them in one order:

ComPtr<IThingZero> ptr0;
ComPtr<IThingOne> ptr1;
ComPtr<IThingTwo> ptr2;
ComPtr<IThingThree> ptr3;

and you call the release in your destructor as you described, they will have Release() called in the order 1, 0, 2, 3 because that's what your destructor calls their functions.

After your destructor finishes everything in your class gets destroyed in the order described. So from the bottom of the class working up, ptr3's destructor will be called, then ptr2, then ptr1, then ptr0, because that's the reverse order of declaration. However, because you've already released the resources in your destructor, their own destructors won't have any work for them to do.

Advertisement