1

我不太明白 shared_ptr 和 C++/CX 中的新句柄符号 (^) 之间的区别。从我读过的内容来看,他们似乎在引用计数和内存管理方面做同样的事情。我错过了什么?

std::shared_ptr<Type>
//vs
Type^
4

2 回答 2

12

仅考虑生命周期管理,它们是相同的: ashared_ptr<T>持有对T对象的强(拥有)引用;aT^也一样。 make_shared<T>大致相当于ref new T在 C++/CX 中。

如果你在任何地方看到T^你认为的shared_ptr<T>orComPtr<T>CComPtr<T>,那没关系 - 生命周期管理大致相同。

但是,生命周期管理在底层的工作方式是不同的:每种格式正确的T类型T^都是实现IUnknown接口的 Windows 运行时引用类型,因此T对象是内部引用计数(*)shared_ptr<T>支持任意类型并使用外部引用计数(即,它分配自己的引用计数机制来控制对象的生命周期)。

对于弱引用,shared_ptr<T>hasweak_ptr<T>T^has WeakReferenceWeakReference不是强类型的,但您可以轻松地围绕它编写强类型的引用包装器。否则,弱引用会按照您的预期工作。对弱引用的支持是可选的:并非所有引用类型都支持弱引用,但大多数都支持。

(*) 有一个例外: Platform::String^,它不是 Windows 运行时引用类型,但出于各种原因被特殊处理。T^不过,在生命周期管理方面,您可以认为它与任何其他方法相同。


那么,为什么 Windows 运行时类型在 C++/CX 中戴帽子呢?为什么不喜欢shared_ptr<T>ComPtr<T>使用图书馆解决方案?

这是因为您永远不会真正拥有指向具体运行时类型的指针(或帽子):您只能通过指向其类型实现的接口之一的指针与对象交互。Windows 运行时也不支持接口或类继承:每个接口都必须直接派生自IInspectable,并且类继承是通过使用 COM 聚合来模拟的。

简而言之,没有库解决方案可以生成具有静态类型安全性的自然 C++ 代码。函数调用、派生到基的转换和接口转换通常需要调用来QueryInterface获取正确的接口指针。

您可以使用库解决方案(例如,参见 WRL 库或几乎任何 COM 代码)来做到这一点,但您不能支持 C++ 语言功能,如隐式转换或dynamic_cast. 没有帽子,您将只能处理接口指针并且不得不调用QueryInterface自己。


(If you're interested in the rationale behind why the C++/CX language extension were developed and how the C++/CLI syntax ended up being selected for reuse, I'd recommend Jim Springfield's post on this blog from last year, "Inside the C++/CX Design". Also of note is episode 3 of GoingNative, in which Marian Luparu discusses C++/CX.)

于 2012-08-24T18:05:17.810 回答
1

据我所知,后者缺乏对弱引用和自定义释放函数的支持。

请注意,前者更通用,接受任何类型(原则上),并且为了安全和清洁要求使用辅助函数make_shared。后者在语言级别上得到支持。这意味着这样的代码在 C++/CX 中是安全的:

some_function(ref new foo(), ref new bar());

在 C++ 中,您需要这样做:

// bad: if foo is allocated but bar's allocation throws, you leak!
some_function(new foo(), new bar());

// good: both never make it anywhere but into a shared_ptr, no leaks
some_function(make_shared<foo>(), make_shared<bar>());

除此之外,当然,它们实现了相同的概念。如果您在 C++/CX 领域,请使用后一种语法以简化和统一;如果您尝试使用标准 C++,或者将现有资源管理方案包装到引用计数方案中,那么您将需要前者。

于 2012-08-24T17:34:13.363 回答