UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
WeakObjectPtr.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3/*=============================================================================
4 WeakObjectPtr.h: Weak pointer to UObject
5=============================================================================*/
6
7#pragma once
8
9#include "CoreTypes.h"
18#include <type_traits>
19
20class FArchive;
21class UObject;
22template <class, class>
23struct TWeakObjectPtr;
24
26#ifndef UE_WEAKOBJECTPTR_ZEROINIT_FIX
27 #define UE_WEAKOBJECTPTR_ZEROINIT_FIX 1
28#endif
29
30namespace UE::Core::Private
31{
33#if UE_WEAKOBJECTPTR_ZEROINIT_FIX
34 inline constexpr int32 InvalidWeakObjectIndex = 0;
35#else
36 inline constexpr int32 InvalidWeakObjectIndex = INDEX_NONE;
37#endif
38}
39
49{
50public:
51
52 template <class, class>
53 friend struct TWeakObjectPtr;
54
55#if UE_WEAKOBJECTPTR_ZEROINIT_FIX
56 FWeakObjectPtr() = default;
57
62#else
65 {
66 Reset();
67 }
68
74 {
75 (*this) = nullptr;
76 }
77#endif
78
79 UE_DEPRECATED(5.6, "Constructing a FWeakObjectPtr from NULL has been deprecated - please use nullptr instead.")
81 {
82 (*this) = nullptr;
83 }
84
97 template <typename T>
100 {
101 // This needs to be a template instead of TObjectPtr<const UObject> because C++ does derived-to-base
102 // pointer conversions ('standard conversion sequences') in situations that TSmartPtr<Derived>-to-TSmartPtr<Base>
103 // conversions ('user-defined conversions') doesn't, meaning it won't auto-convert in many real use cases.
104 //
105 // https://en.cppreference.com/w/cpp/language/implicit_conversion
106 }
107
113
114#if UE_WITH_REMOTE_OBJECT_HANDLE
115 explicit FWeakObjectPtr(FRemoteObjectId RemoteId)
116 {
117 // When using remote object handles both ObjectIndex and SerialNumber are not used when comparing weak object pointers
118 // ObjectIndex is used for performance only and will be updated when this weak pointer is accessed
119 // SerialNumber will also get updated when this weak pointer is resolved
120 ObjectIndex = 0;
121 ObjectSerialNumber = 0;
122 ObjectRemoteId = RemoteId;
123 }
124#endif // UE_WITH_REMOTE_OBJECT_HANDLE
125
129 inline void Reset()
130 {
131 using namespace UE::Core::Private;
132
133 ObjectIndex = InvalidWeakObjectIndex;
134 ObjectSerialNumber = 0;
135#if UE_WITH_REMOTE_OBJECT_HANDLE
137#endif
138 }
139
146 {
147 *this = FObjectPtr(const_cast<UObject*>(Object));
148 }
149 template <typename T>
151 {
152 // This needs to be a template instead of TObjectPtr<const UObject> because C++ does derived-to-base
153 // pointer conversions ('standard conversion sequences') in situations that TSmartPtr<Derived>-to-TSmartPtr<Base>
154 // conversions ('user-defined conversions') doesn't, meaning it won't auto-convert in many real use cases.
155 //
156 // https://en.cppreference.com/w/cpp/language/implicit_conversion
157
158 *this = FObjectPtr(Object);
159 }
160
166
172 inline bool operator==(const FWeakObjectPtr& Other) const
173 {
174 return
175#if UE_WITH_REMOTE_OBJECT_HANDLE
176 ObjectRemoteId == Other.ObjectRemoteId ||
177#else
178 (ObjectIndex == Other.ObjectIndex && ObjectSerialNumber == Other.ObjectSerialNumber) ||
179#endif
180 (!IsValid() && !Other.IsValid());
181 }
182
183#if !PLATFORM_COMPILER_HAS_GENERATED_COMPARISON_OPERATORS
188 inline bool operator!=(const FWeakObjectPtr& Other) const
189 {
190 return
191#if UE_WITH_REMOTE_OBJECT_HANDLE
192 ObjectRemoteId != Other.ObjectRemoteId &&
193#else
194 (ObjectIndex != Other.ObjectIndex || ObjectSerialNumber != Other.ObjectSerialNumber) &&
195#endif
196 (IsValid() || Other.IsValid());
197 }
198#endif
199
205 {
206#if UE_WITH_REMOTE_OBJECT_HANDLE
207 return ObjectRemoteId == Other.ObjectRemoteId;
208#else
209 return ObjectIndex == Other.ObjectIndex && ObjectSerialNumber == Other.ObjectSerialNumber;
210#endif
211 }
212
218 COREUOBJECT_API class UObject* Get(bool bEvenIfGarbage) const;
219
224 COREUOBJECT_API class UObject* Get(/*bool bEvenIfGarbage = false*/) const;
225
228
235
240 COREUOBJECT_API class TStrongObjectPtr<UObject> Pin(/*bool bEvenIfGarbage = false*/) const;
241
242 /*
243 * Get a strong object ptr even if it is marked as Garbage or Unreachable
244 * @return TStrongObjectPtr will be invalid if this object is gone or the weak pointer is explicitly null, otherwise a valid TStrongObjectPtr
245 */
247
248
256
262 COREUOBJECT_API class TStrongObjectPtr<UObject> TryPin(bool& bOutPinValid /*, bool bEvenIfGarbage = false*/) const;
263
264 /*
265 * Attempt to get a strong object ptr even if it is marked as Garbage or Unreachable, but only if garbage collection is not in progress
266 * @param OutResult will be invalid if this object is gone, or the weak pointer is explicitly null, or garbage collection is in progress. Otherwise a valid TStrongObjectPtr
267 * @return true if garbage collection was not in progress, and OutResult was successfully captured, false if garbage collection was in progress and OutResult was not captured
268 */
270
271 // This is explicitly not added to avoid resolving weak pointers too often - use Get() once in a function.
272 explicit operator bool() const = delete;
273
286 COREUOBJECT_API bool IsValid(bool bEvenIfGarbage, bool bThreadsafeTest = false) const;
287
296 COREUOBJECT_API bool IsValid(/*bool bEvenIfGarbage = false, bool bThreadsafeTest = false*/) const;
297
304 COREUOBJECT_API bool IsStale(bool bIncludingGarbage = true, bool bThreadsafeTest = false) const;
305
310 inline bool IsExplicitlyNull() const
311 {
312 using namespace UE::Core::Private;
313#if UE_WITH_REMOTE_OBJECT_HANDLE
314 return !ObjectRemoteId.IsValid();
315#else
316#if UE_WEAKOBJECTPTR_ZEROINIT_FIX
317 return ObjectIndex == InvalidWeakObjectIndex && ObjectSerialNumber == 0;
318#else
319 return ObjectIndex == InvalidWeakObjectIndex;
320#endif
321#endif // UE_WITH_REMOTE_OBJECT_HANDLE
322 }
323
324#if UE_WITH_REMOTE_OBJECT_HANDLE
328 UE_FORCEINLINE_HINT FRemoteObjectId GetRemoteId() const
329 {
330 return ObjectRemoteId;
331 }
332
336 COREUOBJECT_API bool HasSameObject(const UObject* Other) const;
337
341 UE_FORCEINLINE_HINT bool IsRemote() const
342 {
344 }
345#else
347 {
348 return false;
349 }
350#endif // UE_WITH_REMOTE_OBJECT_HANDLE
351
353 inline uint32 GetTypeHash() const
354 {
355#if UE_WITH_REMOTE_OBJECT_HANDLE
356 return ::GetTypeHash(ObjectRemoteId);
357#else
358 return uint32(ObjectIndex ^ ObjectSerialNumber);
359#endif
360 }
361
369
370protected:
371 UE_DEPRECATED(5.1, "GetObjectIndex is now deprecated, and will be removed.")
373 {
374 return ObjectIndex;
375 }
376
377private:
378 inline int32 GetObjectIndex_Private() const
379 {
380#if UE_WITH_REMOTE_OBJECT_HANDLE
381 using namespace UE::Core::Private;
382 if ((ObjectIndex == InvalidWeakObjectIndex) && ObjectRemoteId.IsValid())
383 {
385 }
386#endif
387 return ObjectIndex;
388 }
389
390private:
391 friend struct FObjectKey;
392
393#if UE_WITH_REMOTE_OBJECT_HANDLE
395 COREUOBJECT_API bool CanBeResolved() const;
396#endif
397
402 inline bool SerialNumbersMatch() const
403 {
404#if UE_WITH_REMOTE_OBJECT_HANDLE
405 checkSlow(ObjectIndex >= 0); // otherwise this is a corrupted weak pointer
406 FRemoteObjectId ActualId = GUObjectArray.GetRemoteId(ObjectIndex);
407 return ActualId == ObjectRemoteId;
408#else
409 checkSlow(ObjectSerialNumber > FUObjectArray::START_SERIAL_NUMBER && ObjectIndex >= 0); // otherwise this is a corrupted weak pointer
411 checkSlow(!ActualSerialNumber || ActualSerialNumber >= ObjectSerialNumber); // serial numbers should never shrink
412 return ActualSerialNumber == ObjectSerialNumber;
413#endif
414 }
415
416 inline bool SerialNumbersMatch(FUObjectItem* ObjectItem) const
417 {
418#if UE_WITH_REMOTE_OBJECT_HANDLE
419 checkSlow(ObjectIndex >= 0); // otherwise this is a corrupted weak pointer
420 FRemoteObjectId ActualId = ObjectItem->GetRemoteId();
421 return ActualId == ObjectRemoteId;
422#else
423 checkSlow(ObjectSerialNumber > FUObjectArray::START_SERIAL_NUMBER && ObjectIndex >= 0); // otherwise this is a corrupted weak pointer
424 const int32 ActualSerialNumber = ObjectItem->GetSerialNumber();
425 checkSlow(!ActualSerialNumber || ActualSerialNumber >= ObjectSerialNumber); // serial numbers should never shrink
426 return ActualSerialNumber == ObjectSerialNumber;
427#endif
428 }
429
430 inline FUObjectItem* Internal_GetObjectItem() const
431 {
432 using namespace UE::Core::Private;
433
434#if UE_WITH_REMOTE_OBJECT_HANDLE
435 if (IsExplicitlyNull())
436 {
437 return nullptr;
438 }
439 if (ObjectIndex < 0)
440 {
441 return nullptr;
442 }
443
444 FUObjectItem* ObjectItem = GUObjectArray.IndexToObject(ObjectIndex);
445 bool bResolved = false;
446 // if an existing object is marked as Remote it needs to be resolved before its ObjectItem is returned
447 if (!ObjectItem || ObjectItem->HasAnyFlags(EInternalObjectFlags::Remote))
448 {
449 ObjectItem = TryResolveRemoteObject();
450 if (!ObjectItem)
451 {
452 return nullptr;
453 }
454 bResolved = true;
455 }
456 // TryResolveRemoteObject already validated the serial number
457 if (!bResolved && !SerialNumbersMatch(ObjectItem))
458 {
459 ObjectItem = TryResolveRemoteObject();
460 if (!ObjectItem)
461 {
462 return nullptr;
463 }
464 }
465 return ObjectItem;
466#else
467 if (ObjectSerialNumber == 0)
468 {
469#if UE_WEAKOBJECTPTR_ZEROINIT_FIX
470 checkSlow(ObjectIndex == InvalidWeakObjectIndex); // otherwise this is a corrupted weak pointer
471#else
472 checkSlow(ObjectIndex == 0 || ObjectIndex == -1); // otherwise this is a corrupted weak pointer
473#endif
474
475 return nullptr;
476 }
477
478 if (ObjectIndex < 0)
479 {
480 return nullptr;
481 }
482 FUObjectItem* const ObjectItem = GUObjectArray.IndexToObject(ObjectIndex);
483 if (!ObjectItem)
484 {
485 return nullptr;
486 }
487 if (!SerialNumbersMatch(ObjectItem))
488 {
489 return nullptr;
490 }
491 return ObjectItem;
492#endif // UE_WITH_REMOTE_OBJECT_HANDLE
493 }
494
495#if UE_WITH_REMOTE_OBJECT_HANDLE
500 inline bool Internal_IsValid(bool bEvenIfGarbage, bool bThreadsafeTest) const
501 {
502 using namespace UE::Core::Private;
503
504 if (IsExplicitlyNull())
505 {
506 return false;
507 }
508 if (ObjectIndex < 0)
509 {
510 return false;
511 }
512
513 FUObjectItem* ObjectItem = GUObjectArray.IndexToObject(ObjectIndex);
514 if (!ObjectItem || !SerialNumbersMatch(ObjectItem))
515 {
516 return CanBeResolved();
517 }
518 else if (bThreadsafeTest)
519 {
520 return true;
521 }
522 return GUObjectArray.IsValid(ObjectItem, bEvenIfGarbage);
523 }
524#else
526 inline bool Internal_IsValid(bool bEvenIfGarbage, bool bThreadsafeTest) const
527 {
528 FUObjectItem* const ObjectItem = Internal_GetObjectItem();
529 if (bThreadsafeTest)
530 {
531 return (ObjectItem != nullptr);
532 }
533 else
534 {
535 return (ObjectItem != nullptr) && GUObjectArray.IsValid(ObjectItem, bEvenIfGarbage);
536 }
537 }
538#endif
539
541 inline UObject* Internal_Get(bool bEvenIfGarbage) const
542 {
543 FUObjectItem* const ObjectItem = Internal_GetObjectItem();
544 return ((ObjectItem != nullptr) && GUObjectArray.IsValid(ObjectItem, bEvenIfGarbage)) ? (UObject*)ObjectItem->GetObject() : nullptr;
545 }
546
548 COREUOBJECT_API TStrongObjectPtr<UObject> Internal_TryPin(bool& bOutPinValid, bool bEvenIfGarbage) const;
549
550#if UE_WEAKOBJECTPTR_ZEROINIT_FIX
552 int32 ObjectSerialNumber = 0;
553#else
554 int32 ObjectIndex;
555 int32 ObjectSerialNumber;
556#endif // UE_WEAKOBJECTPTR_ZEROINIT_FIX
557#if UE_WITH_REMOTE_OBJECT_HANDLE
559#endif // UE_WITH_REMOTE_OBJECT_HANDLE
560
561};
562
#define checkSlow(expr)
Definition AssertionMacros.h:332
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
FPlatformTypes::TYPE_OF_NULLPTR TYPE_OF_NULLPTR
The type of the C++ nullptr keyword.
Definition Platform.h:1157
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
const bool
Definition NetworkReplayStreaming.h:178
FUObjectArray GUObjectArray
Definition UObjectHash.cpp:55
UE_REWRITE constexpr T ImplicitConv(typename TIdentity< T >::Type Obj)
Definition UnrealTemplate.h:743
UE_FORCEINLINE_HINT uint32 GetTypeHash(const FWeakObjectPtr &WeakObjectPtr)
Definition WeakObjectPtr.h:564
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Archive.h:1208
FUObjectItem * IndexToObject(int32 Index)
Definition UObjectArray.h:1089
@ START_SERIAL_NUMBER
Definition UObjectArray.h:956
bool IsValid(FUObjectItem *ObjectItem, bool bEvenIfGarbage)
Definition UObjectArray.h:1123
int32 GetSerialNumber(int32 Index)
Definition UObjectArray.h:1312
Definition StrongObjectPtrTemplates.h:26
Definition Object.h:95
implementation
Definition PlayInEditorLoadingScope.h:8
constexpr int32 InvalidWeakObjectIndex
Definition WeakObjectPtr.h:34
bool IsRemote(FRemoteObjectId ObjectId)
Definition RemoteObject.cpp:535
Definition ObjectKey.h:19
Definition ObjectPtr.h:55
Definition RemoteObjectTypes.h:212
UE_FORCEINLINE_HINT uint32 GetTypeHash() const
Definition RemoteObjectTypes.h:274
Definition UObjectArray.h:50
UE_FORCEINLINE_HINT bool HasAnyFlags(EInternalObjectFlags InFlags) const
Definition UObjectArray.h:309
class UObjectBase * GetObject() const
Definition UObjectArray.h:146
int32 GetSerialNumber() const
Definition UObjectArray.h:195
Definition WeakObjectPtr.h:49
UE_FORCEINLINE_HINT FWeakObjectPtr(FObjectPtr Object)
Definition WeakObjectPtr.h:89
FWeakObjectPtr(const FWeakObjectPtr &Other)=default
COREUOBJECT_API class TStrongObjectPtr< UObject > TryPin(bool &bOutPinValid, bool bEvenIfGarbage) const
Definition WeakObjectPtr.cpp:168
FWeakObjectPtr()=default
COREUOBJECT_API class TStrongObjectPtr< UObject > PinEvenIfUnreachable() const
Definition WeakObjectPtr.cpp:149
UE_FORCEINLINE_HINT void operator=(const UObject *Object)
Definition WeakObjectPtr.h:145
COREUOBJECT_API bool IsStale(bool bIncludingGarbage=true, bool bThreadsafeTest=false) const
Definition WeakObjectPtr.cpp:65
UE_FORCEINLINE_HINT void operator=(TObjectPtr< T > Object)
Definition WeakObjectPtr.h:150
UE_FORCEINLINE_HINT bool IsRemote() const
Definition WeakObjectPtr.h:346
COREUOBJECT_API void operator=(FObjectPtr Object)
Definition WeakObjectPtr.cpp:29
UE_FORCEINLINE_HINT FWeakObjectPtr(TObjectPtr< T > Object)
Definition WeakObjectPtr.h:98
COREUOBJECT_API class UObject * GetEvenIfUnreachable() const
Definition WeakObjectPtr.cpp:127
COREUOBJECT_API class TStrongObjectPtr< UObject > Pin() const
Definition WeakObjectPtr.cpp:138
uint32 GetTypeHash() const
Definition WeakObjectPtr.h:353
bool operator!=(const FWeakObjectPtr &Other) const
Definition WeakObjectPtr.h:188
bool HasSameIndexAndSerialNumber(const FWeakObjectPtr &Other) const
Definition WeakObjectPtr.h:204
UE_FORCEINLINE_HINT int32 GetObjectIndex() const
Definition WeakObjectPtr.h:372
bool operator==(const FWeakObjectPtr &Other) const
Definition WeakObjectPtr.h:172
COREUOBJECT_API bool TryPinEvenIfUnreachable(class TStrongObjectPtr< UObject > &OutResult) const
Definition WeakObjectPtr.cpp:178
UE_FORCEINLINE_HINT FWeakObjectPtr(const UObject *Object)
Definition WeakObjectPtr.h:93
FWeakObjectPtr & operator=(const FWeakObjectPtr &Other)=default
void Reset()
Definition WeakObjectPtr.h:129
bool IsExplicitlyNull() const
Definition WeakObjectPtr.h:310
COREUOBJECT_API bool IsValid() const
Definition WeakObjectPtr.cpp:59
UE_FORCEINLINE_HINT FWeakObjectPtr(TYPE_OF_NULLPTR)
Definition WeakObjectPtr.h:58
COREUOBJECT_API class UObject * Get() const
Definition WeakObjectPtr.cpp:116
Definition ObjectPtr.h:488
Definition WeakObjectPtrTemplates.h:25