Обнаруживает ли C ++ / CX и решает циклы объектов?

Из моего понимания C ++ / CX не использует сборку мусора, он использует подсчет ссылок подход вместо этого.

Проблема с подсчетом ссылок заключается в том, что он не может избавиться от циклов. Циклы обычно решаются с использованием слабых ссылок, таких как weak_ptr в стандартном C ++.

Но я не могу найти способ в C ++ / CX явно указать слабую ссылку. Исходя из этого, я бы предположил, что этим занимается сам C ++ / CX. Мне интересно, как C ++ / CX решит эту проблему.

Например, посмотрите на следующий код:

ref class Foo
{
public:
    Bar^ bar;
};

ref class Bar
{
public:
    Foo^ foo;
};

ref class App
{
public:
    virtual void OnLaunched(LaunchActivatedEventArgs^ args)
    {
        Foo^ foo = ref new Foo();
        Bar^ bar = ref new Bar();
        foo.bar = bar;
        bar.foo = foo;
    }
};

Как C ++ / CX обнаруживает этот цикл?

Как C ++ / CX решает этот цикл?

Как C ++ / CX решает, какой из этих объектов должен быть «корневым объектом», а какой - «слабой ссылкой»?


person dalle    schedule 16.09.2011    source источник
comment
Почему он должен определять цикл? Он не может удалить ни один из них, поскольку оба используются, когда вы удаляете последний из этих двух объектов, оба будут освобождены. Сделанный.   -  person RedX    schedule 16.09.2011
comment
Существуют хорошо известные алгоритмы обнаружения циклов для GC с подсчетом ссылок ... secure.wikimedia .org / wikipedia / en / wiki /   -  person CAFxX    schedule 16.09.2011
comment
@RedX: если C ++ / WinRT не обрабатывает циклы, в приложении будет утечка памяти.   -  person dalle    schedule 16.09.2011
comment
@CAFxX: WinRT не использует сборщик мусора.   -  person dalle    schedule 16.09.2011
comment
Сам WinRT поддерживает слабые ссылки - посмотрите C: \ Program Files (x86) \ Windows Kits \ 8.0 \ Include \ winrt \ WeakReference.idl. Однако я еще не знаю, как это спроектировать для расширений языка VC ++.   -  person Pavel Minaev    schedule 16.09.2011


Ответы (6)


Краткий ответ: нет, C ++ / CX не обнаруживает и не решает циклы объектов.

Длинный ответ: сам WinRT имеет стандартный механизм слабых ссылок. На уровне ABI это определяется в терминах интерфейсов IWeakReference и IWeakReferenceSource, которые вы можете увидеть в «% ProgramFiles% \ Windows Kits \ 8.0 \ Include \ winrt \ WeakReference.idl».

В C ++ / CX все ваши классы будут автоматически реализовывать IWeakReferenceSource, и, следовательно, на все их экземпляры можно ссылаться слабо. Чтобы получить и сохранить слабую ссылку на объект, вы должны использовать вспомогательный класс Platform::WeakReference (определенный в vccorlib.h):

Foo^ foo = ref new Foo;
Platform::WeakReference weakRef(foo);

чтобы вернуть объект, используйте Resolve<T>:

foo = weakRef.Resolve<Foo>();

Как обычно, вы получите nullptr, если объект уже уничтожен.

В остальном экземпляр WeakReference ведет себя более или менее как интеллектуальный указатель - он копируемый, перемещаемый, сопоставимый, назначаемый из nullptr, имеет неявное преобразование в неопределенный тип bool и т. Д.

Обратите внимание, что, начиная с бета-версии VS11, IDE Intellisense откажется от WeakReference, если вы попытаетесь его использовать, подчеркнув это волнистыми линиями и т. Д. Однако компилятор может справиться с ними отлично, несмотря на все это.

person Pavel Minaev    schedule 17.09.2011
comment
Хм. еще одна причина не создавать расширения C ++ / CX и придерживаться класса-оболочки weak_ptr ‹›, как мы все этого хотим :) - person gbjbaanb; 14.02.2012
comment
@gbjbaanb Имейте в виду, что это описывает статус-кво на момент предварительной версии для разработчиков. Это не значит, что в будущих выпусках все останется таким же. - person Pavel Minaev; 15.02.2012
comment
конечно, и Microsoft может получить все мои аплодисменты, если она прислушается к нам и изменит неприятный интерфейс в стиле .NET на более естественный. Я думаю, это шанс для MS внести свой вклад в спецификацию модулей, которая, к сожалению, не вошла в последний стандарт, теперь это Boost :: Modules, который также работает как способ доступа к компонентам WinRT, что было бы хорошо. - person gbjbaanb; 24.02.2012
comment
@gbjbaanb C ++ / CX не навязывается вам - если вы предпочитаете ванильный C ++ с шаблонами интеллектуальных указателей и т. д., вы можете использовать это - обычные файлы IDL поставляются для всех интерфейсов WinRT, а WRL - это вспомогательная библиотека с ComPtr<T> и другими вещами. Подробнее см. В этом видео: channel9.msdn.com/Shows/C9-GoingNative/ - person Pavel Minaev; 24.02.2012
comment
Я переписал ответ, чтобы он соответствовал текущему положению дел в бета-версии (которая имеет надлежащую поддержку слабых ссылок в C ++ / CX). - person Pavel Minaev; 21.03.2012

Проверьте Include \ winrt \ WeakReference.h в SDK. Он определяет IWeakReference, который можно использовать для этой цели.

person Steve Rowe    schedule 16.09.2011
comment
Я попытался создать образец, используя reinterpret_cast и друзей, чтобы перейти от T^ к IWeakReferenceSource*, но QI перенастраивает E_NOINTERFACE для классов, определенных через ref class - похоже, они не поддерживают слабые интерфейсы (пока)? Тем не менее, работает для компонентов WinRT из Windows.*. - person Pavel Minaev; 17.09.2011

Это будет тот же старый способ программирования COM, ручное мышление и добавление явных вызовов decf.

person Lothar    schedule 16.09.2011
comment
Бывают случаи, когда это не вариант, например, при установке Window::Current->Content = foo в OnLaunched перед возвратом. - person dalle; 16.09.2011
comment
@Pavel: Вероятно, Декреф выглядел бы как t = nullptr;. - person Ben Voigt; 17.09.2011
comment
Там IWeakReference, так что это не совсем правильный ответ. Однако нужно узнать, как делать слабые ссылки в C ++ / CX. - person Pavel Minaev; 17.09.2011
comment
Из того, что я слышал до сих пор, это самый точный ответ. Там много размахивают руками, но ничего конкретного. Превентивный +1. - person Hans Passant; 17.09.2011

Как сказал Павел Минаев, WinRT имеет стандартный механизм слабых ссылок: интерфейсы _1 _ / _ 2_, вспомогательный класс WRL::WeakRef и так далее.

К сожалению, классы, определенные через ref class, не реализуют IWeakReferenceSource, и, по крайней мере, в этой версии Developer Preview я не смог найти способ добавить этот интерфейс.

Возможный обходной путь - реализовать класс WinRT без использования расширений C ++ / CX на «родном» C ++. Инфраструктура WRL значительно упрощает эту задачу (она делает для WinRT то же, что ATL для COM).

Существует один из примеров WinRT (образец «Создание сервера DLL»), который показывает, как реализовать объект WinRT без использования ref. По умолчанию классы, наследующие от WRL::RuntimeClass<Interface>, автоматически реализуют IWeakReferenceSource и, таким образом, предоставляют слабые ссылки.

person Paolo Severini    schedule 05.10.2011


Это не объекты WinRT, это объекты вашего настраиваемого типа. Поскольку вы объявили их как ссылочные типы .NET (ref class) с использованием синтаксиса C ++ / CLI, они собирают мусор, как и все ссылочные типы .NET, с помощью теста достижимости, а не подсчета ссылок.

Объекты Win32 всегда подсчитывались по ссылкам, поэтому не похоже, что WinRT что-то там меняет. Он просто предоставляет вам классы C ++ RAII, а программисты Win32 написали свои собственные оболочки, чтобы воспользоваться преимуществами RAII.

person Ben Voigt    schedule 16.09.2011
comment
Это не C ++ / CLI, это расширения компонентов VC ++. Синтаксис (в основном) тот же, семантика - нет. В VC ++ / CX ref class может быть пересчитан, и копирование T^ обновит его автоматически. Никакой сборщик мусора не задействован. - person Pavel Minaev; 17.09.2011
comment
@Pavel: Подождите, значит, один и тот же код может быть правильным C ++ / CLI и сломанными расширениями компонентов VC ++? Эта идея должна немедленно умереть. Или по крайней мере требовать #pragma в верхней части каждого файла, чтобы указать, для какой среды сборки он написан. - person Ben Voigt; 17.09.2011
comment
О, теперь я понимаю, вы можете сказать, для какой среды он предназначен, по ref new или gcnew. Все еще очень проблемная идея, ИМО. - person Ben Voigt; 17.09.2011
comment
Есть и другие отличия (например, cli теперь lang, а System::String Platform::String), но вы правы, можно написать код, визуально неотличимый от C ++ / CLI, но с другой семантикой. Однако C ++ / CLI официально не поддерживается в приложениях в стиле Metro. Документы находятся здесь: msdn.microsoft .com / ru-ru / library / windows / apps /; также см. доклад Херба здесь: channel9.msdn.com/Events/BUILD/BUILD2011/ TOOL-532T - с 9:20 - person Pavel Minaev; 17.09.2011