UE4 智慧指標
智慧指標庫:減輕記憶體分配與追蹤負擔 ,C++11中智慧指標的定義實現
- 共享指標TSharedPtr
- 共享引用 TSharedRef(不可為空)
- 弱指標 TWeakPtr
- 助手類與函式
助手類與函式
MakeShareable()
-用於從C ++指標初始化共享指標(啟用隱式轉換)TSharedFromThis
-您可以從this派生自己的類,以從“this
”獲取TSharedRef
StaticCastSharedRef()
-靜態轉換實用工具函式,通常用於向下轉換為派生型別。ConstCastSharedRef()
-將“const
”引用轉換為“可變”智慧引用StaticCastSharedPtr()
-動態強制轉換實用程式函式,通常用於向下轉換為派生型別。ConstCastSharedPtr()
-將“const
”智慧指標轉換為“可變”智慧指標
使用共享引用TSahredRef和指標TSharedPtr等的好處:
- 乾淨的語法:可以像常規C ++指標一樣複製,取消引用和比較共享指標。
- 防止記憶體洩漏: 物件在沒有共享引用的時候
- 弱引用: 弱指標可以安全地檢查物件何時被破壞
- 執行緒安全:可以從多個執行緒安全中訪問的“安全執行緒”
- 無處不在: 可以建立指向幾乎任何物件型別的共享指標
- 執行時安全: 共享引用永遠不會為null,並且始終可以取消引用
- 沒有參考週期(ReferenceCycle): 使用弱指標來破壞參考週期
- 賦予意圖:可以輕鬆地從
觀察者
告訴物件所有者
owner - 效能: 共享指標具有最小的開銷,所有操作都是恆定時間
- 強大的功能:支援’const’,將宣告轉發給不完整的型別,型別轉換等
- 記憶體:只有64位C ++指標大小的兩倍(加上共享的16位元組引用控制器)
侷限性:
- 共享指標與虛幻物件(
UObject
類)不相容! - 當前僅具有常規解構函式的型別(無自定義刪除器)
- 目前尚不支援動態分配的陣列(例如
MakeSharable(new int32 [20])
) - 尚不支援將
TSharedPtr
/TSharedRef
隱式轉換為bool
和(boost:shared_ptr
,std :: shared_ptr
)之類的區別: - 型別名稱和方法名稱與Unreal的程式碼庫更加一致
- 必須使用
Pin()
將弱指標轉換為共享指標(無顯式建構函式)
-執行緒安全功能是可選的,而不是強制的 TSharedFromThis
返回共享的參考,而不是共享的指標- 省略了某些功能(例如use_count(),unique()等)
- 不允許例外(已省略所有相關功能)
- 尚不支援自定義分配器和自定義刪除功能
使用Tips:
- 儘可能使用
TSharedRef
代替TSharedPtr
-永遠不能為nullptr
! - 可以呼叫TSharedPtr :: Reset()`釋放對物件的引用(並可能取消分配)
- 使用
MakeShareable()
輔助函式隱式轉換為TSharedRefs
或TSharedPtrs
- 永遠不能重置
TSharedRef
或將其分配給nullptr
,但是可以為其分配新物件 - 共享的指標假定物件的所有權-無需呼叫
delete self
! - 通常,在將C ++指標傳遞給新的共享指標時,應該“操作新的”
- 將智慧指標作為函式引數而不是
TWeakPtr
傳遞時,請使用TSharedRef
或TSharedPtr
- 智慧指標的“執行緒安全”版本要慢一些-僅在需要時使用它們
- 可以轉發宣告不完整型別的共享指標,就像您期望的那樣!
- 相容型別的共享指標將隱式轉換(例如,向上轉換)
- 可以為
TSharedRef <MyClass>
建立typedef
以使其更容易鍵入 - 為了獲得最佳效能,儘量減少對
TWeakPtr :: Pin
的呼叫(或對TSharedRef
/TSharedPtr
的轉換) - 如果類繼承
TSharedFromThis
,這個類可以將自己作為共享引用返回 - 要向下轉換指向派生物件類的指標,請指向
StaticCastSharedPtr
函式 - 共享指標完全支援
'const'
物件! - 可以使用
ConstCastSharedPtr
函式使'const'
共享指標可變
下面是 SharedPointerTesting.inl
檔案中的一些使用的UE4智慧指標的測試示例
inl檔案:inl檔案是行內函數的原始檔。
行內函數通常在C++標頭檔案中實現,但是當C++標頭檔案中行內函數過多的情況下,
我們想使標頭檔案看起來簡潔點,像普通函式那樣將行內函數宣告和函式定義放在標頭檔案和實現檔案中,
具體做法將是:將行內函數的具體實現放在inl檔案中,然後在該標頭檔案末尾使用#include引入該inl檔案。
/*
"->"箭頭和"(*)."對於智慧指標指向的物件的修改都是有效的,
對於多個智慧指標指向的物件,釋放其中一個智慧指標,其指向的物件並不會被銷燬
*/
{
// Test arrow operator
struct FSharedTest
{
bool bFoo;
};
TSharedPtr< FSharedTest, Mode > SharedArray( new FSharedTest() );
SharedArray->bFoo = true;
// Test dereference operator
( *SharedArray ).bFoo = false;
// Create an additional reference to an existing shared pointer
TSharedPtr< FSharedTest, Mode > OtherSharedArrayReference( SharedArray );
// Release original reference (object should not be destroyed)
SharedArray.Reset();//釋放其中一個智慧指標,其指向的物件並不會被銷燬
// NOTE: OtherSharedArrayReference goes out of scope here (object is destroyed)
}
/*
這幾個智慧指標指向的物件實際上還是同一個物件,但是能獲取到物件的值根據智慧指標的類來決定
*/
{
// Test casting
class FBase
{
bool bFoo;
};
class FDerived
: public FBase
{ };
{
// Explicit downcast to derived shared ptr 顯式的向下轉換為派生類的智慧指標
TSharedPtr< FBase, Mode > DerivedAsBasePtr( new FDerived() );
TSharedPtr< FDerived, Mode > DerivedPtr( StaticCastSharedPtr< FDerived >( DerivedAsBasePtr ) );
}
{
// Initialize base from derived (implicit upcast) 由派生類隱式的向上轉換初始化基類
TSharedPtr< FDerived, Mode > DerivedPtr( new FDerived() );
TSharedPtr< FBase, Mode > BasePtr( DerivedPtr );
}
{
// Assign derived to base (implicit upcast)由派生類隱式的向上轉換分配基類
TSharedPtr< FDerived, Mode > DerivedPtr( new FDerived() );
TSharedPtr< FBase, Mode > BasePtr = DerivedPtr;
}
}
// Test 'const'
/*
總結:
同型別的智慧指標物件可以進行比較,型別不同不能作比較(例如int32和float)
分配const指標(僅引用,可以!)
指向const物件的智慧指標不能隱式轉換為沒有const標記的智慧指標,需要顯式的呼叫ConstCastSharedPtr()
ConstCastSharedPtr()就是將“const”智慧指標轉變為“mutable”智慧指標
“mutable”的智慧指標可以直接分配給“const”型別的智慧指標
舉例:
ConstPtrA=ConstPtrB // √ 分配const指標
ConstPtrA=MutablePtrC // √ 分配const指標
MutablePtrC=ConstPtrB // X 不可以隱式的Const_Cast轉變
MutablePtrC=ConstCastSharedPtr<float>(ConstPtrB) // √ 顯式的呼叫ConstCastSharedPtr(),可以將“const”智慧指標轉變為“mutable”智慧指標
/*
關於TSharedPtr和TShareRef
*/
*************************TSharedPtr*************************
//空物件的 智慧指標 TSharedPtr
TSharedPtr< float, Mode > FloatPtr;//FloatPtr.IsValid()為flase,FloatPtr.Get()為nullptr
TSharedPtr< float, Mode > FloatPtrA = nullptr;
TSharedPtr< float, Mode > FloatPtrA(nullptr);
//給值 TSharedPtr
TSharedPtr< float, Mode > FloatPtr( new float( 1.0f ) );
TSharedPtr< float, Mode > FloatPtr = MakeSharable( new float( 1.0f ) );
TSharedPtr< float, Mode > FloatPtr = new float( 1.0f ); //錯誤
TSharedPtr< float, Mode > FloatPtr = float( 1.0f ); //錯誤
TSharedPtr< float, Mode > FloatPtr (float( 1.0f ));//錯誤
//TSharedPtr之間的
TSharedPtr< float, Mode > FloatPtrA = FloatPtr;//這兩個智慧指標指向同一物件
TSharedPtr< float, Mode > FloatPtrB(FloatPtrA);//FloatPtrB和FloatPtrA智慧指標指向同一個物件
//從TSharedRef到TSharedPtr
TSharedPtr< float, Mode > FloatPtrB(FloatRef);
TSharedPtr< float, Mode > FloatPtrB = FloatRef;
*************************TSharedRef*************************
TSharedRef< float, Mode > FloatRef( new float( 1.0f ) );
TSharedRef< float, Mode > FloatRef = MakeShareable( new float( 123.0f ) );
TSharedRef< float, Mode > FloatRef;//錯誤,TSharedRef沒有預設構造,不會編譯
//TSharedRef沒有隱式建構函式來表示指標(包括nullptr),需要ToSharedRef()函式
TSharedRef< float, Mode > FloatRef = nullptr;//錯誤
TSharedRef< float, Mode > FloatRef = FloatPtr;//錯誤
TSharedRef< float, Mode > FloatRef(FloatPtr)//錯誤
TSharedRef< float, Mode > FloatRef(floatPtr.ToSharedRef());//注意:FloatPtr需要不能為nullptr,否則執行的時候會斷言包錯
TSharedRef< float, Mode > FloatRef = floatPtr.ToSharedRef();//注意:FloatPtr需要不能為nullptr,否則執行的時候會斷言包錯
// TSharedFromThis
{
class FMyClass
: public TSharedFromThis< FMyClass, Mode >
{
public:
TSharedRef< FMyClass, Mode > GetSelfAsShared()
{
return AsShared();//返回的是FMyClass的物件作為TSharedRef(注意:注意這個物件需要已建立例項,且不在物件的解構函式中呼叫)
}
};
// Grab shared pointer to stack-allocated class, before ever assigning it to
// a shared pointer reference. This will trigger an assertion!
if( 0 )//錯誤的:因為MyClass這個物件沒有建立這個物件的例項,在AsShared()中會觸發斷言
{
FMyClass MyClass;
TSharedRef< FMyClass, Mode > TheClassPtr( MyClass.GetSelfAsShared() );
}
TSharedPtr< FMyClass, Mode > TheClassPtr1( new FMyClass() );
{
FMyClass* MyClass = TheClassPtr1.Get();
TSharedRef< FMyClass, Mode > TheClassPtr2( MyClass->GetSelfAsShared() );
}
}
相關文章
- 智慧指標指標
- [CPP] 智慧指標指標
- 什麼是智慧指標?為什麼要用智慧指標?指標
- openfoam 智慧指標探索指標
- vtk智慧指標指標
- 智慧指標學習指標
- 【c++】智慧指標C++指標
- C++智慧指標C++指標
- 智慧指標之手撕共享指標shared_ptr指標
- 批註:智慧指標分析指標
- C++11 智慧指標C++指標
- 「C++」理解智慧指標C++指標
- auto_ptr 智慧指標指標
- SMART POINTER(智慧指標) (轉)指標
- 智慧指標用法學習指標
- 指標+AI:邁向智慧化,讓指標應用更高效指標AI
- C++ 用智慧指標這樣包裝 this 指標是否可行C++指標
- C++進階(智慧指標)C++指標
- C++11智慧指標用法C++指標
- C++ 智慧指標詳解C++指標
- [CareerCup] 13.8 Smart Pointer 智慧指標指標
- NULL 指標、零指標、野指標Null指標
- C++標準庫有四種智慧指標C++指標
- C++筆記(11) 智慧指標C++筆記指標
- 話說智慧指標發展之路指標
- c++ 智慧指標用法詳解C++指標
- C++智慧指標簡單剖析C++指標
- c++ auto_ptr 智慧指標C++指標
- 【C++智慧指標 auto_ptr】C++指標
- Linux 核心裡的“智慧指標”Linux指標
- Spear Parser(一):智慧指標類薦指標
- 野指標 空指標指標
- 智慧指標-使用、避坑和實現指標
- C++11 新特性之智慧指標C++指標
- 正確使用auto_ptr智慧指標指標
- C++11新特性之智慧指標C++指標
- c++ auto_ptr類 智慧指標C++指標
- C++智慧指標模板類複習C++指標