Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Belangrijk
Bouwen met de Windows App SDK? In de code van dit artikel worden UWP-naamruimten (Windows.UI.Xaml) gebruikt. Als uw project gericht is op WinUI 3 (Windows App SDK), vervang dan overal Microsoft.UI.Xaml (en de bijbehorende naamruimten van Microsoft.UI.*). Zie UWP-API's toewijzen aan de Windows App SDK voor een volledige toewijzings- en UI-migratiehandleiding voor meer informatie.
De Windows Runtime is een systeem met referentietelling; in een dergelijk systeem is het belangrijk dat u op de hoogte bent van het belang van, en het onderscheid tussen, sterke en zwakke referenties (en referenties die geen van beide zijn, zoals de impliciete this-pointer). Zoals u in dit onderwerp zult zien, kan weten hoe u deze verwijzingen correct beheert het verschil betekenen tussen een betrouwbaar systeem dat soepel werkt en een systeem dat onvoorspelbaar vastloopt. Door helperfuncties te bieden die uitgebreide ondersteuning bieden in de taalprojectie, ontmoet C++/WinRT u halverwege uw werk aan het bouwen van complexere systemen eenvoudig en correct.
Note
Met slechts enkele uitzonderingen is zwakke referentieondersteuning standaard ingeschakeld voor Windows Runtime typen die u gebruikt of ontwerpt in C++/WinRT. Windows. UI. Samenstelling en Windows. Devices.Input.PenDevice zijn voorbeelden van uitzonderingen: naamruimten waarbij zwakke referentieondersteuning niet is ingeschakeld voor deze typen. Zie ook Als uw gedelegeerde voor automatische intrekking niet kan registreren.
Als u typen maakt, raadpleeg dan de sectie Zwakke verwijzingen in C++/WinRT in dit onderwerp.
Veilige toegang tot de this-pointer in een coroutine van een klasselid
Zie Gelijktijdigheid en asynchrone bewerkingen met C++/WinRT voor meer informatie over coroutines en codevoorbeelden.
De onderstaande code toont een typisch voorbeeld van een coroutine die een memberfunctie van een klasse is. U kunt dit voorbeeld kopiëren en plakken in de opgegeven bestanden in een nieuw Windows Console Application -project (C++/WinRT).
// pch.h
#pragma once
#include <iostream>
#include <winrt/Windows.Foundation.h>
// main.cpp : Defines the entry point for the console application.
#include "pch.h"
using namespace winrt;
using namespace Windows::Foundation;
using namespace std::chrono_literals;
struct MyClass : winrt::implements<MyClass, IInspectable>
{
winrt::hstring m_value{ L"Hello, World!" };
IAsyncOperation<winrt::hstring> RetrieveValueAsync()
{
co_await 5s;
co_return m_value;
}
};
int main()
{
winrt::init_apartment();
auto myclass_instance{ winrt::make_self<MyClass>() };
auto async{ myclass_instance->RetrieveValueAsync() };
winrt::hstring result{ async.get() };
std::wcout << result.c_str() << std::endl;
}
MyClass::RetrieveValueAsync besteedt enige tijd aan het werken en retourneert uiteindelijk een kopie van het MyClass::m_value gegevenslid. Door RetrieveValueAsync aan te roepen wordt een asynchroon object gemaakt, en dat object heeft een impliciete this-aanwijzer (waarmee uiteindelijk toegang wordt verkregen tot m_value).
Houd er rekening mee dat in een coroutine de uitvoering synchroon verloopt tot aan het eerste opschortingspunt, waarop de controle wordt teruggegeven aan de aanroeper. In RetrieveValueAsync is de eerste co_await het eerste onderbrekingspunt. Tegen de tijd dat de coroutine wordt hervat (in dit geval ongeveer vijf seconden later), kan er van alles zijn gebeurd met de impliciete this-pointer via welke we toegang krijgen tot m_value.
Dit is de volledige reeks gebeurtenissen.
- In main wordt een exemplaar van MyClass gemaakt (
myclass_instance). - Het
asyncobject wordt gemaakt en wijst (via deze) naarmyclass_instance. - De winrt::Windows::Foundation::IAsyncAction::get-functie raakt het eerste ophangpunt, blokkeert enkele seconden en retourneert vervolgens het resultaat van RetrieveValueAsync.
-
RetrieveValueAsync retourneert de waarde van
this->m_value.
Stap 4 is alleen veilig zolang dit geldig blijft.
Maar wat gebeurt er als het klasse-exemplaar wordt vernietigd voordat de asynchrone bewerking is voltooid? Er zijn allerlei manieren waarop het klasse-exemplaar buiten het bereik kan vallen voordat de asynchrone methode is voltooid. Maar we kunnen dit simuleren door het klasse-exemplaar in te stellen op nullptr.
int main()
{
winrt::init_apartment();
auto myclass_instance{ winrt::make_self<MyClass>() };
auto async{ myclass_instance->RetrieveValueAsync() };
myclass_instance = nullptr; // Simulate the class instance going out of scope.
winrt::hstring result{ async.get() }; // Behavior is now undefined; crashing is likely.
std::wcout << result.c_str() << std::endl;
}
Nadat we de klasse-instantie vernietigen, lijkt het alsof we er daarna niet meer direct naar verwijzen. Maar natuurlijk heeft het asynchrone object deze aanwijzer en probeert dit te gebruiken om de waarde te kopiëren die is opgeslagen in het klasse-exemplaar. De coroutine is een memberfunctie en gaat ervan uit dat hij zijn this-pointer zonder beperkingen kan gebruiken.
Met deze wijziging in de code ondervinden we een probleem in stap 4, omdat het klasse-exemplaar is vernietigd en dit niet meer geldig is. Zodra het asynchrone object toegang probeert te krijgen tot de variabele in het klasse-exemplaar, loopt het vast (of doet het iets helemaal niet gedefinieerd).
De oplossing is om de asynchrone bewerking (de coroutine) een eigen sterke verwijzing naar het klasse-exemplaar te geven. Zoals het nu is geschreven, houdt de coroutine in feite een ruwe this-pointer naar de klasse-instantie vast; maar dat is niet genoeg om de klasse-instantie levend te houden.
Als u het klasse-exemplaar actief wilt houden, wijzigt u de implementatie van RetrieveValueAsync in die hieronder wordt weergegeven.
IAsyncOperation<winrt::hstring> RetrieveValueAsync()
{
auto strong_this{ get_strong() }; // Keep *this* alive.
co_await 5s;
co_return m_value;
}
Een C++/WinRT-klasse is rechtstreeks of indirect afgeleid van de winrt::implementeert sjabloon. Daarom kan het C++/WinRT-object zijn implements::get_strong-beveiligde memberfunctie aanroepen om een sterke verwijzing naar zijn this-pointer op te halen. Houd er rekening mee dat u de strong_this variabele niet daadwerkelijk hoeft te gebruiken in het bovenstaande codevoorbeeld. Als u gewoon get_strong aanroept, wordt het referentieaantal van het C++/WinRT-object verhoogd en blijft de impliciete waarde van deze aanwijzer geldig.
Belangrijk
Omdat get_strong een lidfunctie is van de winrt::implementeert de structsjabloon, kunt u deze alleen aanroepen vanuit een klasse die direct of indirect is afgeleid van winrt::implements, zoals een C++/WinRT-klasse. Zie Author-API's met C++/WinRT voor meer informatie over het afleiden van winrt::implements en voorbeelden.
Hiermee wordt het probleem opgelost dat we eerder hadden toen we bij stap 4 waren. Zelfs als alle andere verwijzingen naar het klasse-exemplaar verdwijnen, heeft de coroutine de voorzorgsmaatregel genomen om ervoor te zorgen dat de afhankelijkheden stabiel zijn.
Als een sterke verwijzing niet geschikt is, kunt u in plaats daarvan implements::get_weak aanroepen om een zwakke verwijzing naar this te verkrijgen. Bevestig dat u een sterke verwijzing kunt ophalen voordat u toegang krijgt tot dit bestand. Nogmaals, get_weak is een lidfunctie van de winrt::implementeert struct-sjabloon.
IAsyncOperation<winrt::hstring> RetrieveValueAsync()
{
auto weak_this{ get_weak() }; // Maybe keep *this* alive.
co_await 5s;
if (auto strong_this{ weak_this.get() })
{
co_return m_value;
}
else
{
co_return L"";
}
}
In het bovenstaande voorbeeld voorkomt de zwakke verwijzing niet dat de klasse-instantie wordt vernietigd wanneer er geen sterke verwijzingen meer zijn. Maar hiermee kunt u controleren of er een sterke verwijzing kan worden verkregen voordat u toegang krijgt tot de lidvariabele.
Veilige toegang tot deze aanwijzer met een gemachtigde voor gebeurtenisafhandeling
Het scenario
Zie Gebeurtenissen afhandelen met behulp van gemachtigden in C++/WinRT voor algemene informatie over het afhandelen van gebeurtenissen.
In de vorige sectie werden mogelijke levensduurproblemen rond coroutines en concurrentie belicht. Maar als u een gebeurtenis verwerkt met de lidfunctie van een object of vanuit een lambda-functie binnen de lidfunctie van een object, moet u nadenken over de relatieve levensduur van de ontvanger van de gebeurtenis (het object dat de gebeurtenis verwerkt) en de gebeurtenisbron (het object dat de gebeurtenis aangeeft). Laten we eens kijken naar enkele codevoorbeelden.
De onderstaande codevermelding definieert eerst een eenvoudige EventSource-klasse , die een algemene gebeurtenis genereert die wordt verwerkt door gedelegeerden die eraan zijn toegevoegd. Dit voorbeeld van een gebeurtenis maakt toevallig gebruik van het delegaattype Windows::Foundation::EventHandler, maar de hier beschreven problemen en oplossingen zijn van toepassing op alle delegaattypen.
Vervolgens biedt de klasse EventRecipient een handler voor de EventSource::Event-gebeurtenis in de vorm van een lambda-functie.
// pch.h
#pragma once
#include <iostream>
#include <winrt/Windows.Foundation.h>
// main.cpp : Defines the entry point for the console application.
#include "pch.h"
using namespace winrt;
using namespace Windows::Foundation;
struct EventSource
{
winrt::event<EventHandler<int>> m_event;
void Event(EventHandler<int> const& handler)
{
m_event.add(handler);
}
void RaiseEvent()
{
m_event(nullptr, 0);
}
};
struct EventRecipient : winrt::implements<EventRecipient, IInspectable>
{
winrt::hstring m_value{ L"Hello, World!" };
void Register(EventSource& event_source)
{
event_source.Event([&](auto&& ...)
{
std::wcout << m_value.c_str() << std::endl;
});
}
};
int main()
{
winrt::init_apartment();
EventSource event_source;
auto event_recipient{ winrt::make_self<EventRecipient>() };
event_recipient->Register(event_source);
event_source.RaiseEvent();
}
Het patroon is dat de ontvanger van de gebeurtenis een lambda-handler heeft voor de gebeurtenis, die afhankelijk is van de this-aanwijzer. Wanneer de ontvanger van de gebeurtenis de gebeurtenisbron overleeft, overleeft de ontvanger ook die afhankelijkheden. En in die gevallen, die gebruikelijk zijn, werkt het patroon goed. Sommige van deze gevallen zijn duidelijk, bijvoorbeeld wanneer een UI-pagina een gebeurtenis verwerkt die wordt gegenereerd door een besturingselement dat zich op de pagina bevindt. De pagina bestaat langer dan de knop — dus de handler bestaat ook langer dan de knop. Dit geldt telkens wanneer de ontvanger de bron bezit (bijvoorbeeld als datalid), of wanneer de ontvanger en de bron siblings van elkaar zijn en rechtstreeks eigendom zijn van hetzelfde andere object.
Wanneer u zeker weet dat u een situatie hebt waarin de handler de this waarvan deze afhankelijk is niet zal overleven, dan kunt u this normaal capturen, zonder rekening te houden met een sterke of zwakke lifetime.
Maar er zijn nog steeds gevallen waarin dit het gebruik ervan niet overleeft in een handler (inclusief handlers voor voltooiings- en voortgangsevenementen die zijn gegenereerd door asynchrone acties en bewerkingen), en het is belangrijk om te weten hoe u ermee omgaat.
- Wanneer een gebeurtenisbron de gebeurtenissen synchroon genereert, kunt u de handler intrekken en erop vertrouwen dat u geen gebeurtenissen meer ontvangt. Maar bij asynchrone gebeurtenissen kan zelfs na het intrekken van de registratie (en vooral wanneer dat in de destructor gebeurt) een gebeurtenis die al onderweg is uw object nog bereiken nadat de destructie ervan al is begonnen. Het probleem kan worden opgelost door een plaats te vinden om u af te melden voordat het wordt vernietigd, maar lees verder voor een robuuste oplossing.
- Als u een coroutine ontwerpt om een asynchrone methode te implementeren, is het mogelijk.
- In zeldzame gevallen met bepaalde XAML UI-frameworkobjecten (SwapChainPanel, bijvoorbeeld) is dit mogelijk als de ontvanger wordt gefinaliseerd zonder zich af te melden bij de gebeurtenisbron.
Het probleem
Deze volgende versie van de hoofdfunctie simuleert wat er gebeurt wanneer de ontvanger van de gebeurtenis wordt vernietigd (misschien valt deze buiten het bereik) terwijl de gebeurtenisbron nog steeds gebeurtenissen genereert.
int main()
{
winrt::init_apartment();
EventSource event_source;
auto event_recipient{ winrt::make_self<EventRecipient>() };
event_recipient->Register(event_source);
event_recipient = nullptr; // Simulate the event recipient going out of scope.
event_source.RaiseEvent(); // Behavior is now undefined within the lambda event handler; crashing is likely.
}
De ontvanger van de gebeurtenis wordt vernietigd, maar de lambda-gebeurtenishandler daarin is nog steeds geabonneerd op de gebeurtenis Event. Wanneer die gebeurtenis wordt geactiveerd, probeert de lambdafunctie de this-pointer te derefereren, die op dat moment ongeldig is. Een toegangsschending resulteert dus uit code in de handler (of in de voortzetting van een coroutine) die deze probeert te gebruiken.
Belangrijk
Als u een dergelijke situatie tegenkomt, moet u nadenken over de levensduur van het object ; en of het vastgelegde object de opname wel of niet overleeft. Als dat niet zo is, legt u het vast met een sterke of zwakke verwijzing, zoals hieronder wordt beschreven.
Of—als dat in uw scenario zinvol is, en als overwegingen rond threading dat überhaupt mogelijk maken—dan kunt u er ook voor kiezen om de handler te herroepen nadat de ontvanger de gebeurtenis heeft afgehandeld, of in de destructor van de ontvanger. Zie Een geregistreerde gemachtigde intrekken.
Zo registreren we de handler.
event_source.Event([&](auto&& ...)
{
std::wcout << m_value.c_str() << std::endl;
});
De lambda legt automatisch lokale variabelen vast op basis van verwijzing. In dit voorbeeld kunnen we dit dus op dezelfde manier hebben geschreven.
event_source.Event([this](auto&& ...)
{
std::wcout << m_value.c_str() << std::endl;
});
In beide gevallen leggen we alleen de onbewerkte aanwijzer vast. En dat heeft geen effect op de referentietelling, dus niets verhindert dat het huidige object wordt vernietigd.
De oplossing
De oplossing is om een sterke verwijzing vast te leggen (of, zoals we zullen zien, een zwakke verwijzing als dat geschikter is). Met een sterke verwijzing wordt het aantal verwijzingen verhoogd en blijft het huidige object actief. U declareert alleen een capture-variabele (in dit voorbeeld genoemd strong_this ) en initialiseert deze met een aanroep voor implementaties::get_strong, waarmee een sterke verwijzing naar deze aanwijzer wordt opgehaald.
Belangrijk
Omdat get_strong een lidfunctie is van de winrt::implementeert de structsjabloon, kunt u deze alleen aanroepen vanuit een klasse die direct of indirect is afgeleid van winrt::implements, zoals een C++/WinRT-klasse. Zie Author-API's met C++/WinRT voor meer informatie over het afleiden van winrt::implements en voorbeelden.
event_source.Event([this, strong_this { get_strong()}](auto&& ...)
{
std::wcout << m_value.c_str() << std::endl;
});
U kunt zelfs de automatische opname van het huidige object weglaten en toegang krijgen tot het gegevenslid via de opnamevariabele in plaats van via impliciet dit.
event_source.Event([strong_this { get_strong()}](auto&& ...)
{
std::wcout << strong_this->m_value.c_str() << std::endl;
});
Als een sterke verwijzing niet geschikt is, kunt u in plaats daarvan implements::get_weak aanroepen om een zwakke verwijzing naar this te verkrijgen. Een zwakke verwijzing houdt het huidige object niet in leven. Controleer dus of u nog steeds een sterke verwijzing kunt ophalen uit de zwakke verwijzing voordat u toegang krijgt tot leden.
event_source.Event([weak_this{ get_weak() }](auto&& ...)
{
if (auto strong_this{ weak_this.get() })
{
std::wcout << strong_this->m_value.c_str() << std::endl;
}
});
Als u een ruwe pointer vastlegt, moet u ervoor zorgen dat het object waarnaar wordt verwezen in leven blijft.
Als u een lidfunctie als gemachtigde gebruikt
Naast lambda-functies zijn deze principes ook van toepassing op het gebruik van een lidfunctie als uw gedelegeerde. De syntaxis is anders, dus laten we eens kijken naar wat code. Eerst volgt hier de mogelijk onveilige eventhandler voor de memberfunctie, met een ruwe this-pointer.
struct EventRecipient : winrt::implements<EventRecipient, IInspectable>
{
winrt::hstring m_value{ L"Hello, World!" };
void Register(EventSource& event_source)
{
event_source.Event({ this, &EventRecipient::OnEvent });
}
void OnEvent(IInspectable const& /* sender */, int /* args */)
{
std::wcout << m_value.c_str() << std::endl;
}
};
Dit is de standaard, conventionele manier om te verwijzen naar een object en de bijbehorende lidfunctie. Om dit veilig te maken, kunt u vanaf versie 10.0.17763.0 (Windows 10 versie 1809) van de Windows SDK een sterke of zwakke verwijzing instellen op het punt waarop de handler is geregistreerd. Op dat moment is bekend dat het eventontvangerobject nog bestaat.
Voor een sterke referentie roept u gewoon get_strong aan in plaats van de ruwe this-pointer. C++/WinRT zorgt ervoor dat de resulterende delegate een sterke verwijzing naar het huidige object behoudt.
event_source.Event({ get_strong(), &EventRecipient::OnEvent });
Het vastleggen van een sterke verwijzing betekent dat uw object pas in aanmerking komt voor vernietiging nadat de handler niet is geregistreerd en alle openstaande callbacks zijn geretourneerd. Deze garantie is echter alleen geldig op het moment dat de gebeurtenis wordt geactiveerd. Als uw eventhandler asynchroon is, moet u uw coroutine vóór het eerste onderbrekingspunt een sterke verwijzing naar de klasse-instantie geven (raadpleeg voor meer informatie en code de sectie Veilig toegang krijgen tot de aanwijzer this in een coroutine van een klasselid eerder in dit onderwerp). Maar dat maakt een kringverwijzing tussen de gebeurtenisbron en uw object, dus u moet dat expliciet verbreken door uw gebeurtenis af te roepen.
Roep get_weak aan voor een zwakke verwijzing. C++/WinRT zorgt ervoor dat de resulterende delegate een zwakke verwijzing vasthoudt. Op het laatste moment en achter de schermen probeert de delegate de zwakke verwijzing om te zetten in een sterke verwijzing, en roept de memberfunctie alleen aan als dat lukt.
event_source.Event({ get_weak(), &EventRecipient::OnEvent });
Als de gedelegeerde uw lidfunctie aanroept , houdt C++/WinRT uw object actief totdat de handler terugkeert. Als uw handler echter asynchroon is, keert deze terug bij onderbrekingspunten, en moet u uw coroutine vóór het eerste onderbrekingspunt een sterke verwijzing naar de instantie van de klasse geven. Nogmaals, zie voor meer informatie de sectie Veilige toegang tot de this-pointer in een coroutine van een klassenlid eerder in dit onderwerp.
Als de lidfunctie geen deel uitmaakt van een Windows Runtime type
Wanneer de methode get_strong niet beschikbaar is (uw type is geen Windows Runtime type), kunt u de techniek gebruiken die wordt weergegeven in het onderstaande codevoorbeeld. Hier ziet u een reguliere C++-klasse (met de naam ConsoleNetworkWatcher) die de gebeurtenis NetworkInformation.NetworkStatusChanged verwerkt.
#include <winrt/Windows.Networking.Connectivity.h>
using namespace winrt;
using namespace Windows::Networking::Connectivity;
class ConsoleNetworkWatcher
{
/* any constructor, and instance methods, here*/
static void Initialize(std::shared_ptr<ConsoleNetworkWatcher> instance)
{
auto weakPointer{ std::weak_ptr{ instance } };
instance->m_statusChangedRevoker =
NetworkInformation::NetworkStatusChanged(winrt::auto_revoke,
[weakPointer](winrt::Windows::Foundation::IInspectable const& sender)
{
auto sharedPointer{ weakPointer.lock() };
if (sharedPointer)
{
sharedPointer->NetworkStatusChanged(sender);
}
});
}
void NetworkStatusChanged(winrt::Windows::Foundation::IInspectable const& sender){/* handle event here */};
private:
NetworkInformation::NetworkStatusChanged_revoker m_statusChangedRevoker;
};
Een zwak referentievoorbeeld met SwapChainPanel::CompositionScaleChanged
In dit codevoorbeeld gebruiken we de gebeurtenis SwapChainPanel::CompositionScaleChanged als nog een voorbeeld van zwakke verwijzingen. De code registreert een gebeurtenisverwerker met een lambda die een zwakke verwijzing naar de ontvanger vastlegt.
winrt::Microsoft::UI::Xaml::Controls::SwapChainPanel m_swapChainPanel;
winrt::event_token m_compositionScaleChangedEventToken;
void RegisterEventHandler()
{
m_compositionScaleChangedEventToken = m_swapChainPanel.CompositionScaleChanged([weak_this{ get_weak() }]
(Microsoft::UI::Xaml::Controls::SwapChainPanel const& sender,
Windows::Foundation::IInspectable const& object)
{
if (auto strong_this{ weak_this.get() })
{
strong_this->OnCompositionScaleChanged(sender, object);
}
});
}
void OnCompositionScaleChanged(Microsoft::UI::Xaml::Controls::SwapChainPanel const& sender,
Windows::Foundation::IInspectable const& object)
{
// Here, we know that the "this" object is valid.
}
In de lamba capture-component wordt een tijdelijke variabele gemaakt, die een zwakke verwijzing naar deze variabele vertegenwoordigt. Als in het lichaam van de lambda een sterke verwijzing naar dit kan worden verkregen, wordt de functie OnCompositionScaleChanged aangeroepen. Op die manier kan dit veilig worden gebruikt in OnCompositionScaleChanged.
Zwakke verwijzingen in C++/WinRT
Hierboven zagen we zwakke verwijzingen in gebruik. Over het algemeen zijn ze goed voor het breken van cyclische verwijzingen. Voor de systeemeigen implementatie van het op XAML gebaseerde UI-framework, vanwege het historische ontwerp van het framework, is het zwakke referentiemechanisme in C++/WinRT nodig om cyclische verwijzingen af te handelen. Buiten XAML hoeft u waarschijnlijk geen zwakke verwijzingen te gebruiken (niet dat er inherent XAML-specifieke verwijzingen zijn). In plaats daarvan moet u, vaker dan niet, uw eigen C++/WinRT-API's zo ontwerpen dat er geen cyclische verwijzingen en zwakke verwijzingen nodig zijn.
Voor elk type dat u declareert, is het voor C++/WinRT niet meteen duidelijk of en wanneer zwakke verwijzingen nodig zijn. C++/WinRT biedt dus automatisch zwakke referentieondersteuning op de structsjabloon winrt::implementeert, waaruit uw eigen C++/WinRT-typen direct of indirect worden afgeleid. Het is betalen voor play, omdat het u niets kost, tenzij uw object daadwerkelijk wordt opgevraagd voor IWeakReferenceSource. En u kunt er expliciet voor kiezen om van die ondersteuning af te zien.
Codevoorbeelden
De winrt::weak_ref-structsjabloon is één optie voor het verkrijgen van een zwakke verwijzing naar een klasse-exemplaar.
Class c;
winrt::weak_ref<Class> weak{ c };
U kunt ook de helperfunctie winrt::make_weak gebruiken.
Class c;
auto weak = winrt::make_weak(c);
Het maken van een zwakke verwijzing heeft geen invloed op het aantal verwijzingen op het object zelf; het zorgt ervoor dat alleen een besturingsblok wordt toegewezen. Dat controleblok zorgt voor het implementeren van de zwakke verwijzingssemantiek. Vervolgens kunt u proberen om de zwakke verwijzing naar een sterke verwijzing te promoten en, indien succesvol, te gebruiken.
if (Class strong = weak.get())
{
// use strong, for example strong.DoWork();
}
Mits er nog een andere sterke verwijzing bestaat, verhoogt de aanroep van weak_ref::get de referentietelling en retourneert deze de sterke verwijzing aan de aanroeper.
Uitschakelen van ondersteuning voor zwakke verwijzingen
Ondersteuning voor zwakke referenties gebeurt automatisch. U kunt er echter voor kiezen om u expliciet af te wijzen voor deze ondersteuning door de markeringsstruct winrt::no_weak_ref als sjabloonargument door te geven aan uw basisklasse.
Als u rechtstreeks overerft van winrt::implements.
struct MyImplementation: implements<MyImplementation, IStringable, no_weak_ref>
{
...
}
Als u een runtimeklasse schrijft.
struct MyRuntimeClass: MyRuntimeClassT<MyRuntimeClass, no_weak_ref>
{
...
}
Het maakt niet uit waar in het variadische parameterpakket de marker-struct voorkomt. Als u een zwakke referentie aanvraagt voor een type dat is uitgesloten, geeft de compiler de melding "Dit is alleen voor ondersteuning voor zwakke referenties".
Belangrijke API's
Windows developer