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
29
C++11 Smart Pointers
Matt
March 11, 2015
Tweet
Share
More Decks by Matt
See All by Matt
C++11 Lambda
chchwy
1
60
Other Decks in Technology
See All in Technology
NOT A HOTEL SOFTWARE DECK (2025/11/06)
notahotel
0
2.8k
251029 JAWS-UG AI/ML 退屈なことはQDevにやらせよう
otakensh
0
180
Boxを“使われる場”にする統制と自動化の仕組み
demaecan
0
190
プロダクト開発と社内データ活用での、BI×AIの現在地 / Data_Findy
sansan_randd
1
800
東京大学「Agile-X」のFPGA AIデザインハッカソンを制したソニーのAI最適化
sony
0
190
データエンジニアとして生存するために 〜界隈を盛り上げる「お祭り」が必要な理由〜 / data_summit_findy_Session_1
sansan_randd
1
940
最近読んで良かった本 / Yokohama North Meetup #10
mktakuya
0
430
DMMの検索システムをSolrからElasticCloudに移行した話
hmaa_ryo
0
360
GPUをつかってベクトル検索を扱う手法のお話し~NVIDIA cuVSとCAGRA~
fshuhe
0
370
Mackerelにおけるインシデント対応とポストモーテム - 現場での工夫と学び
taxin
0
110
AWSが好きすぎて、41歳でエンジニアになり、AAIを経由してAWSパートナー企業に入った話
yama3133
2
230
Oracle Database@Google Cloud:サービス概要のご紹介
oracle4engineer
PRO
0
430
Featured
See All Featured
Stop Working from a Prison Cell
hatefulcrawdad
272
21k
Music & Morning Musume
bryan
46
6.9k
Building a Scalable Design System with Sketch
lauravandoore
463
33k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
How to Ace a Technical Interview
jacobian
280
24k
Building Applications with DynamoDB
mza
96
6.7k
The Pragmatic Product Professional
lauravandoore
36
7k
Speed Design
sergeychernyshev
32
1.2k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.3k
Building Adaptive Systems
keathley
44
2.8k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.2k
Building an army of robots
kneath
306
46k
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)