读书笔记_Effective_C++_条款十五:在资源类管理类中提供对原始资源的访问
2013-05-26 17:03
555 查看
先放上自己写的MySharedPtr类,这是仿照shared_ptr的功能来实现的(实际shared_ptr要复杂的多)。
这个MySharedPtr已经可以进行资源管理了,当资源的生命周期结束后,可以自动将之删除。但对于使用者来说,还是会遇到一些问题,比如:
因为PrintIntPointerValue函数需要原始指针,但MySharedPtr类中并没有提供这一个接口,所以如果像上面程序一样强行使用,就会报编译错,如下所示:
解决的方法其实挺简单的,就是在类中添加一个名为get()的函数,这个函数返回原始指针。也许会有人质疑这种做法,因为这样原始指针的阴影又会浮现出来,它提供了一个让用户可能出错的接口。
但书上有句话说的好:一个好的class应是“隐藏了客户不需要看的部分,但备妥客户需要的所有东西”。
除了get()外,也可以使用隐式转换函数:
但这种方法往往会使程序陷入漏洞之中,比如:
MySharedPtr<int> sharedPtr(new int(3));
int *ordinaryPtr = sharedPtr; // 这样编译会通过,但一旦sharedPtr释放资源后,ordinaryPtr便会成为悬空指针(ordinaryPtr并会使引用计数加一,也不会参与到资源释放的操作中来)
所以一般而言,提供一个get()函数是比较好的选择。另外,为了方便访问,还应该重载*和->操作符,使得MySharedPtr对象的操作与原始指针的操作一样方便,如下所示:
最后总结一下(MysharedPtr的完整版本可以参照条款十四的读书笔记):
一些应用程序接口往往要求访问到原始资源,所以每一个RAII类都应该提供一个“取得所管理之资源”的方法
对原始资源的访问可能经由显式或隐式转换。一般而言显式转换比较安全(用get而不用operator T*())
#ifndef MY_SHARED_PTR_H #define MY_SHARED_PTR_H #include <iostream> using namespace std; typedef void (*FP)(); template <class T> class MySharedPtr { private: T *ptr; size_t *count; FP Del; // 声明一个删除器 static void swap(MySharedPtr& obj1, MySharedPtr& obj2) { std::swap(obj1.ptr, obj2.ptr); std::swap(obj1.count, obj2.count); std::swap(obj1.Del, obj2.Del); } public: MySharedPtr(T* p = NULL): ptr(p), count(new size_t(1)),Del(NULL){} // 添加带删除器的构造函数 MySharedPtr(T* p, FP fun): ptr(p), count(new size_t(1)), Del(fun){} MySharedPtr(MySharedPtr& p): ptr(p.ptr), count(p.count), Del(p.Del) { ++ *p.count; } MySharedPtr& operator= (MySharedPtr& p) { if(this != &p && (*this).ptr != p.ptr) { MySharedPtr temp(p); swap(*this, temp); } return *this; } ~MySharedPtr() { if(Del != NULL) { Del(); } reset(); } void reset() { -- *count; if(*count == 0) { delete ptr; ptr = 0; delete count; count = 0; } } bool unique() const { return *count == 1; } size_t use_count() const { return *count; } }; #endif /* MY_SHARED_PTR_H */
这个MySharedPtr已经可以进行资源管理了,当资源的生命周期结束后,可以自动将之删除。但对于使用者来说,还是会遇到一些问题,比如:
void PrintIntPointerValue(int* p) { cout << *p << endl; } int main() { MySharedPtr<int> ptr(new int(2)); PrintIntPointerValue(ptr); }
因为PrintIntPointerValue函数需要原始指针,但MySharedPtr类中并没有提供这一个接口,所以如果像上面程序一样强行使用,就会报编译错,如下所示:
解决的方法其实挺简单的,就是在类中添加一个名为get()的函数,这个函数返回原始指针。也许会有人质疑这种做法,因为这样原始指针的阴影又会浮现出来,它提供了一个让用户可能出错的接口。
但书上有句话说的好:一个好的class应是“隐藏了客户不需要看的部分,但备妥客户需要的所有东西”。
除了get()外,也可以使用隐式转换函数:
operator T*() const { return ptr; }
但这种方法往往会使程序陷入漏洞之中,比如:
MySharedPtr<int> sharedPtr(new int(3));
int *ordinaryPtr = sharedPtr; // 这样编译会通过,但一旦sharedPtr释放资源后,ordinaryPtr便会成为悬空指针(ordinaryPtr并会使引用计数加一,也不会参与到资源释放的操作中来)
所以一般而言,提供一个get()函数是比较好的选择。另外,为了方便访问,还应该重载*和->操作符,使得MySharedPtr对象的操作与原始指针的操作一样方便,如下所示:
T& operator* () const { return *ptr; } T* operator-> () const { return ptr; } T* get() const { return ptr; }
最后总结一下(MysharedPtr的完整版本可以参照条款十四的读书笔记):
一些应用程序接口往往要求访问到原始资源,所以每一个RAII类都应该提供一个“取得所管理之资源”的方法
对原始资源的访问可能经由显式或隐式转换。一般而言显式转换比较安全(用get而不用operator T*())
相关文章推荐
- Effective C++ -----条款15:在资源管理类中提供对原始资源的访问
- Effective C++——》条款15:在资源类管理类中提供对原始资源的访问
- 读书笔记《Effective c++》 条款15 在资源管理类中提供对原始资源的访问
- 读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问
- 读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问
- Effective C++ Item 15 在资源管理类中提供对原始资源的访问
- 读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问
- 读书笔记《Effective C++》条款15:在资源管理类中提供对原始资源的访问
- 读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问
- 读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问
- 读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问
- 读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问
- 条款15 在资源管理类中提供对原始资源的访问
- 条款15:在资源管理类中提供对原始资源的访问
- 《Effective C++》学习笔记条款15 在资源管理类中提供对原始资源的访问
- C++ 在资源管理类中提供对原始资源的访问
- 条款15:在资源管理类中提供对原始资源的访问
- C++之在资源管理类中提供对原始资源的访问(15)---《Effective C++》
- 读书笔记_Effective_C++_条款十四:在资源管理类中小心copying行为
- 条款15:在资源管理类中提供对原始资源的访问