C++智慧指標
阿新 • • 發佈:2020-10-14
Smart Pointer
std::unique_ptr - single ownership
std::shared_ptr - shared ownership
std::weak_ptr - temp / no ownership
為什麼使用智慧指標?
void bar(Entity* e) { // who owns e? // How long is e's life cycle? // Should I delete e? } void foo() { Entity* e = new Entity(); e->DoSomething(); bar(e); } foo();// out of scope, memory leak
void bar(std::unique_ptr<Entity> e) { // bar owns e // e will be automatically destoryed } void foo() { auto e = std::unique_ptr<Entity>(); e->DoSomething(); bar(std::move(e)); } foo(); // no memory leak
1、建立unique_ptr
1 std::unique_ptr<Entity> e1 = new Entity();//non-assignable 2 std::unique_ptr<Entity> e1(new Entity()); //OK 3 std::unique_ptr<Entity> e1 = std::make_unique<Entity>(); //preferred 4 auto e2 = std::make_unique<Entity>(); //preferred 5 std::unique_ptr<Entity> e2 = e1; //non-copyable 6 std::unique_ptr<Entity> e2 = std::move(e1); //moveable, transfer ownership 7 foo(std::move(e1)); //transfer ownership
Example:
1 #include <cstdio> 2 #include <iostream> 3 #include <memory> 4 #include <string> 5 6 using namespace std; 7 8 class Entity { 9 public: 10 Entity() { puts("Entity created!"); } 11 ~Entity() { puts("Entity destoried!"); } 12 }; 13 14 void ex1() { 15 puts("------------"); 16 puts("Entering ex1"); 17 { 18 puts("Entering ex1::scope1"); 19 auto e1 = make_unique<Entity>(); 20 puts("Leaveing ex1::scope1"); 21 } 22 puts("Entering ex1"); 23 } 24 25 void foo(unique_ptr<Entity>) { 26 puts("Entering foo"); 27 puts("leaving foo"); 28 } 29 30 void ex2() { 31 puts("------------"); 32 puts("Entering ex2"); 33 auto e1 = make_unique<Entity>(); 34 foo(move(e1)); 35 // e1 was destoried. 36 puts("Leaving ex2"); 37 } 38 39 int main(int argc, char const *argv[]) { 40 ex1(); 41 ex2(); 42 return 0; 43 }
2、unique_ptr的生命週期
建立shared_ptr
1 std::shared_ptr<Entity> e1 = std::make_shared<Entity>(); // preferred 2 std::shared_ptr<Entity> e1(new Entity()); // OK 3 auto e1 = std::make_shared<Entity>(); // preferred 4 std::shared_ptr<Entity> e2 = e1; // copyable,use_count+1 5 std::shared_ptr<Entity> e2 = std::move(e1); // moveable, use_count remains 6 foo(std::move(e1)); // use_count remains 7 foo(e1); // use_count+1
example:
#include <cstdio> #include <iostream> #include <memory> #include <string> using namespace std; class Entity { public: Entity() { puts("Entity created!"); } ~Entity() { puts("Entity destoried!"); } }; oid ex3() { puts("-------------"); puts("Entering ex3"); auto e1 = make_shared<Entity>(); cout << e1.use_count() << endl; { puts("Entering ex3::scope1"); auto e2 = e1; cout << e1.use_count() << endl; auto e3 = move(e2); cout << e1.use_count() << endl; puts("Leaving ex3:scope1"); } cout << e1.use_count() << endl; puts("Leaving ex3"); } int main(int argc, char const *argv[]) { // ex1(); // ex2(); ex3(); return 0; }
out:
shared_ptr的生命週期
在fun1中建立了shared_ptr,transfer給fun2後引用計數還是1,在func2中用多執行緒呼叫了fun3,fun4,fun5,shared給它們
小結:
1.儘量使用智慧指標而不是裸指標
2.優先使用unique_ptr
unique_ptr
正常情況下分配與釋放動態記憶體:
#include <iostream> #include <memory> #include <string> using namespace std; int main(void) { string *str = new(string("hello world")); delete str; //需要手動去釋放
return 0; }
使用智慧指標unique_ptr
unique_ptr<string> pointer(new string("hello world")); // pointer是一個棧變數,在棧變數被回收後動態記憶體也會被回收 cout << *pointer << '\n';