以前学智能指针时有点想当然了,一直以为智能指针很智能,不管你让它管理的是单个资源还是连续的资源它都能正确的将资源释放,现在发现自己大错特错。
先看代码:
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 }