您的位置:首页 > 移动开发 > Objective-C

虚幻4 OBJECT内存分配和初始化

2016-09-28 02:15 423 查看
首先,蓝图调用实在CPP调用之后执行。

模块加载时候回调用所有的UClass的CreateDefaultObject函数,产生默认的OBJECT,以后拷贝默认的就行了

在任何一个Actor构造函数里面打断点,然后play

UnrealEngine\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp

UObject* StaticConstructObject_Internal
(
UClass*			InClass,
UObject*		InOuter								/*=GetTransientPackage()*/,
FName			InName								/*=NAME_None*/,
EObjectFlags	InFlags								/*=0*/,
EInternalObjectFlags InternalSetFlags /*=0*/,
UObject*		InTemplate							/*=NULL*/,
bool bCopyTransientsFromClassDefaults	/*=false*/,
FObjectInstancingGraph* InInstanceGraph				/*=NULL*/
)
{
SCOPE_CYCLE_COUNTER(STAT_ConstructObject);
UObject* Result = NULL;

#if WITH_EDITORONLY_DATA
UE_CLOG(GIsSavingPackage && InOuter != GetTransientPackage(), LogUObjectGlobals, Fatal, TEXT("Illegal call to StaticConstructObject() while serializing object data! (Object will not be saved!)"));
#endif

checkf(!InTemplate || InTemplate->IsA(InClass) || (InFlags & RF_ClassDefaultObject), TEXT("StaticConstructObject %s is not an instance of class %s and it is not a CDO."), *GetFullNameSafe(InTemplate), *GetFullNameSafe(InClass)); // template must be an instance of the class we are creating, except CDOs

// Subobjects are always created in the constructor, no need to re-create them unless their archetype != CDO or they're blueprint generated.
// If the existing subobject is to be re-used it can't have BeginDestroy called on it so we need to pass this information to StaticAllocateObject.
const bool bIsNativeClass = InClass->HasAnyClassFlags(CLASS_Native | CLASS_Intrinsic);
const bool bIsNativeFromCDO = bIsNativeClass &&
(
!InTemplate ||
(InName != NAME_None && InTemplate == UObject::GetArchetypeFromRequiredInfo(InClass, InOuter, InName, InFlags))
);
#if WITH_HOT_RELOAD
// Do not recycle subobjects when performing hot-reload as they may contain old property values.
const bool bCanRecycleSubobjects = bIsNativeFromCDO && !GIsHotReload;
#else
const bool bCanRecycleSubobjects = bIsNativeFromCDO;
#endif
bool bRecycledSubobject = false;
Result = StaticAllocateObject(InClass, InOuter, InName, InFlags, InternalSetFlags, bCanRecycleSubobjects, &bRecycledSubobject);
check(Result != NULL);
// Don't call the constructor on recycled subobjects, they haven't been destroyed.
if (!bRecycledSubobject)
{
FScopeCycleCounterUObject ConstructorScope(InClass, GET_STATID(STAT_ConstructObject));
(*InClass->ClassConstructor)( FObjectInitializer(Result, InTemplate, bCopyTransientsFromClassDefaults, true, InInstanceGraph) );
}

if( GIsEditor && GUndo && (InFlags & RF_Transactional) && !(InFlags & RF_NeedLoad) && !InClass->IsChildOf(UField::StaticClass()) )
{
// Set RF_PendingKill and update the undo buffer so an undo operation will set RF_PendingKill on the newly constructed object.
Result->MarkPendingKill();
SaveToTransactionBuffer(Result, false);
Result->ClearPendingKill();
}
return Result;
}


Result = StaticAllocateObject(InClass, InOuter, InName, InFlags, InternalSetFlags, bCanRecycleSubobjects, &bRecycledSubobject);

上面这一行分配内存

(*InClass->ClassConstructor)( FObjectInitializer(Result, InTemplate, bCopyTransientsFromClassDefaults, true, InInstanceGraph) );

上面这一行调用构造函数,我猜应该是先把上面构造那个默认的给拷贝过来,然后再调用下面的初始化函数。

参数类型为FObjectInitializer的构造函数是在自动生成的generate.h文件中声明的,类似于这样,我的这个类名是AGame1Character

#define Game1_Source_Game1_Game1Character_h_9_STANDARD_CONSTRUCTORS \
/** Standard constructor, called after all reflected properties have been initialized */ \
NO_API AGame1Character(const FObjectInitializer& ObjectInitializer); \
DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(AGame1Character) \
DECLARE_VTABLE_PTR_HELPER_CTOR(NO_API, AGame1Character); \
DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(AGame1Character); \


DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL这个宏是这样

#define DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(TClass) \

static void __DefaultConstructor(const FObjectInitializer& X) { new((EInternal*)X.GetObj())TClass(X);

enum EInternal {EC_InternalUseOnlyConstructor};

placement new 直接在返回的object指针位置调用了构造函数。然后就调到我们写的构造函数,(上面那个还有个无参数版本,类似于  TClass())

引擎一开始先开辟一个数组,存放所有的活着的UOBJECT。其实就是个Object的指针和这个object的flag。

maloc其实就是单纯的开辟内存,目前没有发现内存池在哪里。在我的PC上是英特尔的TBB算法(TBB(intel threading building blocks)内存分配算法)。

Engine_Updating\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectArray.cpp

void FUObjectArray::AllocateObjectPool(int32 InMaxUObjects, int32 InMaxObjectsNotConsideredByGC)
{
check(IsInGameThread());

MaxObjectsNotConsideredByGC = InMaxObjectsNotConsideredByGC;

// GObjFirstGCIndex is the index at which the garbage collector will start for the mark phase.
// If disregard for GC is enabled this will be set to an invalid value so that later we
// know if disregard for GC pool has already been closed (at least once)
ObjFirstGCIndex = DisregardForGCEnabled() ? -1 : 0;

// Pre-size array.
check(ObjObjects.Num() == 0);
UE_CLOG(InMaxUObjects <= 0, LogUObjectArray, Fatal, TEXT("Max UObject count is invalid. It must be a number that is greater than 0."));
ObjObjects.PreAllocate(InMaxUObjects);

if (MaxObjectsNotConsideredByGC > 0)
{
ObjObjects.AddRange(MaxObjectsNotConsideredByGC);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  虚幻