std :: shared_ptr <type>和Type ^ </type>之间的区别

时间:2012-08-24 17:30:12

标签: c++ c++11 windows-runtime c++-cx

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

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

2 个答案:

答案 0 :(得分:12)

仅考虑终身管理,这些是相同的:shared_ptr<T>拥有对T对象的强大(拥有)引用; T^做同样的事。 make_shared<T>大致相当于C ++ / CX中的ref new T

如果到处都有您认为T^shared_ptr<T>ComPtr<T>的{​​{1}},那就没关系 - 生命周期管理大致相同。

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

对于弱引用,shared_ptr<T>shared_ptr<T>weak_ptr<T>T^WeakReference不是强类型的,但您可以轻松地在其周围编写强类型的引用包装。否则,弱引用会像您期望的那样工作。对弱引用的支持是可选的:并非所有引用类型都支持弱引用,但大多数引用类型都支持弱引用。

(*)有一个例外:WeakReference,它不是Windows运行时引用类型,但由于各种原因而特别处理。但是,您可以将其视为与终身管理方面的任何其他Platform::String^相同。


那么,为什么Windows运行时类型会在C ++ / CX中戴帽子呢?为什么不使用T^shared_ptr<T>这样的库解决方案?

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

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

您可以使用库解决方案(例如,参见WRL库或几乎任何COM代码)来执行此操作,但您不能支持隐式转换或QueryInterface等C ++语言功能。如果没有帽子,你就只能处理接口指针而不得不自己打电话给dynamic_cast


(如果您对为什么开发C ++ / CX语言扩展以及如何最终选择C ++ / CLI语法以供重用的原因感兴趣,我建议Jim Springfield的帖子在去年的博客上"Inside the C++/CX Design"。另外值得注意的是episode 3 of GoingNative,其中Marian Luparu讨论了C ++ / CX。)

答案 1 :(得分: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 ++,或者将现有资源管理方案包装到引用计数方案中,那么您将需要前者。