Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
C++11 Smart Pointers
Search
Matt
March 11, 2015
Technology
0
27
C++11 Smart Pointers
Matt
March 11, 2015
Tweet
Share
More Decks by Matt
See All by Matt
C++11 Lambda
chchwy
1
59
Other Decks in Technology
See All in Technology
10分でわかるfreeeのQA
freee
0
260
バッチ処理のSLOをどう設計するか
rynsuke
7
590
#51 “Empowering Azure Storage with RDMA”
cafenero_777
3
220
生成AIの不確実性と向き合うためのオブジェクト指向設計
tkikuchi1002
2
700
エバンジェリスト活動を7年やってきて見えてきた、コミュニティとエバンジェリストの関係
soracom
PRO
1
200
MongoDB Atlas Vectorsearchではじめる生成AIアプリ開発
chie8842
3
510
エンジニアブランディングチームの KPI / KPI's of engineer branding team
chaspy
1
140
オーティファイ会社紹介資料 / Autify Company Deck
autifyhq
7
100k
サービス成長と共に肥大化するモノレポ、長くなるCI時間 / As services grow, monorepos get bigger and CI time gets longer
kohbis
5
2.1k
データ化エンジニアとしての1年を振り返る
sansantech
PRO
3
260
現実世界の事象から学ぶSOLID原則
h0r15h0
25
10k
データマネジメントを支える武器としてのメタデータ管理
10xinc
2
920
Featured
See All Featured
Imperfection Machines: The Place of Print at Facebook
scottboms
257
12k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
657
120k
The Straight Up "How To Draw Better" Workshop
denniskardys
227
130k
GitHub's CSS Performance
jonrohan
1023
450k
What's new in Ruby 2.0
geeforr
335
31k
Typedesign – Prime Four
hannesfritz
36
2k
Facilitating Awesome Meetings
lara
39
5.5k
Rebuilding a faster, lazier Slack
samanthasiow
72
8.2k
Reflections from 52 weeks, 52 projects
jeffersonlam
343
19k
GraphQLとの向き合い方2022年版
quramy
28
12k
A Philosophy of Restraint
colly
195
15k
Automating Front-end Workflow
addyosmani
1353
200k
Transcript
C++11 Smart Pointers 2015-03-10 Matthew
Outline • Why smart pointer? • std::unique_ptr • std::shared_ptr •
std::weak_ptr • Conclusion
Why smart pointer? 當我們拿到一個 Foo* ptr 時... 1. 你其實不知道它是單一物件還是 array.
2. 你不知道該怎麼銷毀它. a. delete ? delete[] ? ->Release()? Finalize()? 3. 保證(考慮所有路線可能後)剛好 delete 一次. 4. 你不知道這個指標是否還有效... …from Effective Modern C++
Smart pointer! • C++11 引入三種 smart pointer 來管理資源. • #include
<memory> • unique_ptr: for exclusive-ownership. • share_ptr: for shared-ownership. • weak_ptr: if pointers that can dangle.
for exclusive-ownership std::unique_ptr
std::uniqre_ptr • 最簡單的 smart pointer • 適用於物件只有一個 owner 時 •
當 unique_ptr 消滅時, 會順帶釋放持有資源.
適用場景 void f() { ClassA* ptr = new ClassA; …
// do something delete ptr; } if ( error ) { return; }
適用場景 void f() { std::unique_ptr<ClassA> ptr(new ClassA); … // do
something if ( error ) { return; } //delete ptr; no longer necessary. }
建立 unique_ptr // 傳入 raw pointer unique_ptr< string > up(
new string("nico") ); // 使用 make_unique function auto up = make_unique< string >( "nico" );
std::unique_ptr 用法 // unique_ptr 覆寫了 *, -> 運算子 // 所以用法和一般
pointer 差不多 (*up)[0] = 'N'; up->append("lai"); cout << *up << endl;
std::unique_ptr 管理動態分配陣列 // 也可以管理陣列, 用[]運算子存取 unique_ptr< int[] > up2( new
int[10] ); for ( int i = 0; i < 10; ++i) cout << up2[ i ];
std::unique_ptr 檢查 // 檢查指標有效性 if ( up ) { …
} if ( up != nullptr ) { … } // 釋放所有權 (立刻釋放資源) up.release();
std::unique_ptr 用法 // 不接受隱式轉換成 raw pointer (Compiler Error!) unique_ptr<string> up
= new string(""); string* p = up; // 如果你真的要取得 raw pointer… string* p = up.get(); //後果自行負責
// 不能分享所有權, 也不能copy unique_ptr unique_ptr<string> up2 = up; (Compiler Error!)
// 要用 std::move 顯式轉移 unique_ptr<string> up2 = std::move(up); // 轉移之後up失去所有權, onwer 變成了up2 cout << (up == nullptr); // true cout << (up2 == nullptr); // false
std::unique_ptr tips vector< unique_ptr<string> > kVec; // up 不能複製, 要用
reference 的方式取 for ( auto& up : kVec ) { cout << *up; }
std::unique_ptr 很適合持有 member class MyClass { unique_ptr<Foo> m_spFoo; public: MyClass()
: m_spFoo( make_unique<Foo>( 1, "Bar" ) ) {} ~MyClass() { /* 不需要在 destructor 釋放資源 */ } void DoSomething() { m_spFoo->bar(); } };
for shared-ownership. std::shared_ptr
std::shared_ptr 概念 • 由多個物件共享該資源的持有權 • 允許多個 smart pointer 指向同一個物件 •
只有所有的 shared_ptr 都消滅後,才會釋放 持有資源 (reference count)
建立 std::shared_ptr // 傳入 raw_pointer shared_ptr<string> sp( new string("nico") );
// 呼叫 make_shared function (Recommend!) // make_shared is more efficient. auto sp = make_shared<string>( "nico" );
std::shared_ptr 用法 auto sp = make_shared<string>( "nico" ); cout <<
(*sp)[ 0 ]; // print 'n' sp->replace(0, 1, 'N'); // "Nico" string* p = sp.get(); // get raw pointer if ( sp ) { … } if ( sp != nullptr ) { … } if ( sp == nullptr ) { … }
std::shared_ptr 可以分享持有權 auto sp = make_shared< QImage >( "icon.png" );
auto sp2( sp ); // via copy constructor auto sp3 = sp; // via assignment DoSomething( sp ); // pass as parameter sp.reset(); // 釋放所有權 sp2.reset( new QImage ); // 改持有另一個 raw ptr
std::shared_ptr 可以分享持有權 auto sp = make_shared< string >( "nico" );
auto sp2 = sp; vector< shared_ptr<string> > kVec; kVec.push_back( sp ); kVec.push_back( sp2 ); cout << sp.use_count() << endl; // 4
specify deleter // shared_ptr 可以指定釋放資源的方式 FILE* fp = fopen("log.txt", "w");
shared_ptr<FILE> sp( fp, CloseFile ); void CloseFile( FILE* f ) { cout << "File Closed!"; fclose( f ); }
specify deleter // shared_ptr 可以指定釋放資源的方式 FILE* fp = fopen("log.txt", "w");
shared_ptr<FILE> sp( fp, [] ( FILE* f ) { cout << "File Closed!"; fclose(f); } );
type cast // static_pointer_cast() // dynamic_pointer_cast() // const_pointer_cast() void f(
share_ptr<CBase> spBase ) { share_ptr<CNode> spNode = dynamic_pointer_cast< CNode >( spBase ); }
if pointers that can dangle. std::weak_ptr
std::weak_ptr 概念 • 有時候我們不希望共享物件的"持有權"… • 但是又不想用 raw pointer… • 用
weak_ptr! • weak_ptr 可以存取 shared_ptr 管理的物件, 但是不會增加 ref count.
避免 reference cycle Bank Customer share_ptr<Customer> share_ptr<Bank> 無法自動釋放!! share_ptr<Bank>
避免 reference cycle Bank Customer share_ptr<Customer> weak_ptr<Bank> 自動釋放OK!! share_ptr<Bank>
建立 weak_ptr // weak_ptr 不能單獨存在! weak_ptr<QImage> wp( new QImage );
// 必須依附於 shared_ptr. shared_ptr<QImage> sp( new QImage("icon.png") ); weak_ptr<QImage> wp( sp );
weak_ptr 用法 // weak_ptr 「沒有」覆寫 *, -> 運算子 // 所以不能像一般
pointer 使用 weak_ptr< string > wp( sp ); (*wp)[0] = 'N'; // Compiler Error! wp->append("lai"); // Compiler Error!
// 必須呼叫 lock() 轉成 share_ptr 才能用 weak_ptr< string > wp(
sp2 ); if ( auto& sp = wp.lock() ) { sp->append( "lai" ); cout << *sp; } else { cout << "Object is deleted."; }
weak_ptr 用法 weak_ptr< string > wp( sp ); // weak_ptr
可以 copy weak_ptr< string > wp2 = wp; wp.reset(); // 釋放物件指標 wp.expired(); // 詢問物件還在否?
auto sp = make_shared<string>( "Hello" ); weak_ptr<string> wp( sp );
cout << *sp ; // print 'Hello' cout << *wp.lock() ; // print 'Hello' cout << wp.expired(); // print 'false' sp.reset(); // release resource. cout << wp.expired(); // print 'true' cout << *wp.lock(); // throw exception!
Dangerous! Don't do that. CImage* pImage = new CImage; //
不要用兩個 smart pointer 管理同一個 raw pointer !! share_ptr<CImage> sp( pImage ); share_ptr<CImage> sp2( pImage );
Conclusion • C++11 想要消滅 delete keyword. • C++11 想要消滅 90%
的 new keyword. • 思考資源的持有權, 來挑選 smart pointer. • 如果不確定要用哪個, 先選 unique_ptr ◦ 因為 unique_ptr 幾乎沒有 cost • share_ptr 有一些 cost ◦ double pointer size (space cost) ◦ reference count. (performance cost)
Reference • http://www.cplusplus.com/reference/memory/ • MSDN: How to: Create and Use
shared_ptr Instances • The C++ Standard Library 2ed. (Book) • Effective Modern C++ (Book)