以前學智能指針時有點想當然了,一直以為智能指針很智能,不管你讓它管理的是單個資源還是連續的資源它都能正確的將資源釋放,現在發現自己大錯特錯。
先看代碼:
1 #include <iostream> 2 #include <memory> 3 using namespace std; 4 class Test 5 { 6 public: 7 Test() { cout << "Test is construct" << endl; } 8 ~Test() { cout << "Test is destruct" << endl; } 9 };
case1:管理單個資源
1 int main() 2 { 3 shared_ptr<Test> pTest(new Test); 4 return 0; 5 }
這種情況是沒有問題的,程序結束時自動釋放資源,控制台輸出"Test is construct" 和 "Test is destruct"。
case2:管理連續資源
首先,我們知道c++里釋放單個資源和連續資源的語法是不一樣的,前者用delete,后者用delete[ ]
如:
1 int main() 2 { 3 Test* pSingle = new Test; 4 delete pSingle; 5 Test* pSerial = new Test[5]; 6 delete[] pSingle; 7 }
那么如何用智能指針管理呢?
錯誤的示范:
1 int main() 2 { 3 shared_ptr<Test> pTest(new Test[5]); 4 return 0; 5 }
輸出結果如下:
nice,成功滴讓系統報了錯。那么問題出在哪兒?
其實上述的代碼和下面這段代碼的效果相同:
1 int main() 2 { 3 Test* pSerial = new Test[5]; 4 delete pSerial; 5 return 0; 6 }
系統需要的是delete[ ],而你給他的確實delete,系統當然不樂意咯。
正確的姿勢:
上面的例子可以看出,share_ptr的析構函數的默認功能是對你傳進去的資源進行delete操作。
但我們此時的需要是對該指針進行delete[ ]操作,怎么實現?
實現share_ptr的大佬們很體貼的為我們提供了這樣的一種方式:我們在構造share_ptr對象的時候,可能額外滴傳進去一個參數。
template< class Y, class Deleter > shared_ptr( Y* ptr, Deleter d );
shara_ptr析構的時候,將用我們傳進去的Deleter對資源進行析構操作。
Deleter的形式可以有多種,如重載過()的類、函數、lambda等等。
1 void destructTest(Test* pt) 2 { 3 cout << "call this destruct" << endl; 4 delete[] pt; 5 } 6 7 class DestructTest 8 { 9 public: 10 void operator()(Test* pt) 11 { 12 cout << "call this destruct" << endl; 13 delete[] pt; 14 } 15 }; 16 17 int main() 18 { 19 //shared_ptr<Test> pTest(new Test[5], DestructTest()); 20 //shared_ptr<Test> pTest(new Test[5], destructTest); 21 shared_ptr<Test> pTest(new Test[5], [](Test* pt) 22 { 23 cout << "call this destruct" << endl; 24 delete[] pt; 25 }); 26 return 0; 27 }