After really thinking about this, I feel like I must've missed something obvious, and glibmm must keep a lazily initialised dictionary of wrapped widgets to free later, or something. :) But I suspect tracking down the relevant code is still beyond my current level of skill.
// This is a factory function that converts any type to
// its C++ wrapper instance by looking up a wrap_new() function in a map.
//
ObjectBase*
wrap_auto(GObject* object, bool take_copy)
{
if (!object)
return nullptr;
// Look up current C++ wrapper instance:
ObjectBase* pCppObject = ObjectBase::_get_current_wrapper(object);
if (!pCppObject)
{
// There's not already a wrapper: generate a new C++ instance.
pCppObject = wrap_create_new_wrapper(object);
// [...]}// take_copy=true is used where the GTK+ function doesn't do
// an extra ref for us, and always for plain struct members.
if (take_copy)
pCppObject->reference();
return pCppObject;
}