Я не очень понимаю разницу между shared_ptr и новой нотацией дескриптора (^) в C++/CX. Из того, что я читал, кажется, что они делают то же самое в отношении подсчета ссылок и управления памятью. Что мне не хватает?
std::shared_ptr<Type>
//vs
Type^
Я не очень понимаю разницу между shared_ptr и новой нотацией дескриптора (^) в C++/CX. Из того, что я читал, кажется, что они делают то же самое в отношении подсчета ссылок и управления памятью. Что мне не хватает?
std::shared_ptr<Type>
//vs
Type^
Исключительно с точки зрения управления временем жизни, они одинаковы: shared_ptr<T>
содержит строгую (владеющую) ссылку на объект T
; T^
делает то же самое. make_shared<T>
примерно эквивалентно ref new T
в C++/CX.
Если везде, где вы видите T^
, вы думаете, что это shared_ptr<T>
, ComPtr<T>
или CComPtr<T>
, то все в порядке — управление временем жизни примерно одинаково.
Однако внутреннее управление временем жизни работает иначе: каждый тип T
, для которого T^
имеет правильный формат, является эталонным типом среды выполнения Windows, реализующим интерфейс IUnknown
, поэтому объект T
имеет внутренний подсчет ссылок(*) суп>. shared_ptr<T>
поддерживает произвольные типы и использует внешний подсчет ссылок (т. е. выделяет собственный механизм подсчета ссылок для управления временем жизни объекта).
Для слабых ссылок shared_ptr<T>
имеет weak_ptr<T>
, а T^
имеет WeakReference
. WeakReference
не является строго типизированным, но вы можете легко написать вокруг него строго типизированную ссылочную оболочку. В противном случае слабые ссылки работают так, как вы ожидаете. Поддержка слабых ссылок необязательна: не все типы ссылок поддерживают слабые ссылки, но большинство.
(*) Существует одно исключение: Platform::String^
, который не является ссылочным типом среды выполнения Windows, но обрабатывается специально по ряду причин. Однако вы можете считать его таким же, как и любой другой T^
в отношении управления жизненным циклом.
Итак, почему типы среды выполнения Windows носят шляпы в C++/CX? Почему не используется такое библиотечное решение, как shared_ptr<T>
или ComPtr<T>
?
Это потому, что у вас никогда не будет указателя (или шляпы) на конкретный тип среды выполнения: вы можете взаимодействовать с объектом только через указатель на один из интерфейсов, которые реализует его тип. Среда выполнения Windows также не поддерживает наследование интерфейса или класса: каждый интерфейс должен быть производным непосредственно от IInspectable
, а наследование классов эмулируется с помощью агрегации COM.
Короче говоря, не существует библиотечного решения, которое привело бы к естественно выглядящему коду C++ со статической безопасностью типов. Вызовы функций, преобразования из производных в базовые и преобразования интерфейсов обычно требуют вызова QueryInterface
для получения правильного указателя интерфейса.
Вы можете сделать это с помощью библиотечного решения (см., например, библиотеку WRL или почти любой код COM), но вы не можете поддерживать такие функции языка C++, как неявные преобразования или dynamic_cast
. Без шляп вы застряли, имея дело исключительно с указателями интерфейса и должны сами вызывать QueryInterface
.
(Если вам интересно, почему было разработано почему расширение языка C++/CX и как синтаксис C++/CLI был выбран для повторного использования, я бы порекомендовал запись Джима Спрингфилда в этом блоге. прошлого года, "Внутри дизайна C++/CX". следует отметить эпизод 3 GoingNative, в котором Мариан Лупару обсуждает C++/CX.)
Насколько я могу судить, в последнем отсутствует поддержка слабых ссылок и пользовательских функций освобождения.
Обратите внимание, что первый, будучи более общим, принимает любой тип (в принципе) и для безопасности и чистоты требует использования вспомогательной функции make_shared
. Последнее поддерживается на уровне языка. Это означает, что такой код безопасен в C++/CX:
some_function(ref new foo(), ref new bar());
Находясь в С++, вам нужно сделать это:
// 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++ или оборачиваете существующую схему управления ресурсами в схему с подсчетом ссылок, вам подойдет первая.
Type^
не является правильным ни в одной из двух версий языка, что приводит к очевидному ответу: Разница в том, что одна из них является конструкцией C++11. а другой нет - person David Rodríguez - dribeas   schedule 24.08.2012T^
— это функция C++/CX,std::shared_ptr<T>
— это функция C++, и вопрос касается обоих. - person James McNellis   schedule 24.08.2012std::shared_ptr
доступен в c++/CX (т.е. вопрос не в сравнении функций на разных языках, а скорее в сравнении двух функций, доступных в одном конкретном языке. - person David Rodríguez - dribeas   schedule 24.08.2012