从聚合COM对象到聚合对象的QueryInterface调用是否需要特殊处理?

从聚合COM对象到聚合对象的QueryInterface调用是否需要特殊处理?,com,aggregation,Com,Aggregation,与10年前相比,现在更难找到像样的文档,所以我要试试运气,看看是否有人记得聚合规则,因为MSDN文档不清楚。我特别质疑外部(聚合)对象的: 如果外部对象查询指向任何内部对象接口的指针,则必须调用其控制IUnknown释放方法。要释放此指针,外部对象调用其控制IUnknown AddRef方法,然后在内部对象的指针上释放 它有一个代码示例 // Obtaining inner object interface pointer pUnkInner->QueryInterface(IID_IS

与10年前相比,现在更难找到像样的文档,所以我要试试运气,看看是否有人记得聚合规则,因为MSDN文档不清楚。我特别质疑外部(聚合)对象的:

如果外部对象查询指向任何内部对象接口的指针,则必须调用其控制IUnknown释放方法。要释放此指针,外部对象调用其控制IUnknown AddRef方法,然后在内部对象的指针上释放

它有一个代码示例

// Obtaining inner object interface pointer 
pUnkInner->QueryInterface(IID_ISomeInterface, &pISomeInterface); 
pUnkOuter->Release(); 

// Releasing inner object interface pointer 
pUnkOuter->AddRef(); 
pISomeInterface->Release(); 
我的问题是:这有必要吗?它可以防止什么情况?当指针的寿命长于方法调用时,如何实现它

我特别想知道,如果聚合对象公开其内部对象接口(这是聚合的全部要点),它将如何执行这个引用计数舞蹈?如果聚合对象将内部对象的接口返回给它的调用方,它将传递引用的所有权,它将不知道调用方何时处理完它,调用方也不知道他正在处理聚合


(我认为这个问题应该是独立的,但是以前当我问一些没有具体代码的问题时,有人会抱怨,如果你真的需要我提供我正在处理的聚合类的示例代码来回答,我可以添加它。我认为这不应该是必要的,也不会给这个问题增加任何价值,这是相当标准的。)

文本是在外部对象的上下文中获得对内部接口的访问权以供其私人使用。由于内部对象将其
AddRef
转发回外部对象(请参见
CImpSomeInterface::AddRef
),如果您没有执行
punkOuter->Release()
,你将创建一个循环引用。如果QI的结果将被分发,那么你交给的人将进行一次释放,以平衡转发的QI创建的AddRef,一切都会好起来。@RaymondChen,我明白了,这是有意义的,谢谢!我想释放的舞蹈主要是为了记账初始化目的和对称性?考虑到内部接口会将释放转发到外部对象。如前所述,讨论是在对象获取并缓存指向其自身内部对象的指针的上下文中进行的。如果您不遵循QI进行释放,您将以循环引用结束,从而导致泄漏。是的,抱歉,由于您之前的解释,我理解了这一部分,它是关于“释放内部对象接口指针”的后半部分。根据您的解释,它看起来像一个no-op(AddRef在外部,然后是转发的释放),除了可能内部对象接口版本,除了转发到外部对象版本之外,可能正在做一些日志记录,否则这些日志记录将不会是对称的?我不想省略它,只是确保我正确理解了场景。文本是在外部对象为其自身获得内部接口访问权限的上下文中私用。由于内部对象将其
AddRef
转发回外部对象(请参见
CImpSomeInterface::AddRef
),如果您没有执行
punkOuter->Release()
,你将创建一个循环引用。如果QI的结果将被分发,那么你交给的人将进行一次释放,以平衡转发的QI创建的AddRef,一切都会好起来。@RaymondChen,我明白了,这是有意义的,谢谢!我想释放的舞蹈主要是为了记账初始化目的和对称性?考虑到内部接口会将释放转发到外部对象。如前所述,讨论是在对象获取并缓存指向其自身内部对象的指针的上下文中进行的。如果您不遵循QI进行释放,您将以循环引用结束,从而导致泄漏。是的,抱歉,由于您之前的解释,我理解了这一部分,它是关于“释放内部对象接口指针”的后半部分。根据您的解释,它看起来像一个no-op(AddRef在外部,然后是转发的释放),除了可能内部对象接口发行版,除了转发到外部对象发行版之外,可能正在做一些日志记录,否则就不对称了?我不想省略它,只是确保我正确理解了场景。