Customising std::shared_ptr or boost::shared_ptr to throw an exception on NULL dereference

谁说我不能喝 提交于 2020-01-02 03:50:49

问题


I have a few projects that use boost::shared_ptr or std::shared_ptr extensively (I can convert to either implementation soon enough, if there is a good answer to this question for one, but not the other). The Boost implementation uses Boost.Assert to avoid returning in the case of encountering an empty (NULL) pointer in operator* or operator-> at runtime; while the libc++ implementation seems to lack any check.

While of course the validity of a shared_ptr should be checked before use, a large, mixed-paradigm codebase leads me to want to try an exception-throwing variation; as most of the code is relatively exception-aware and will at most fail to a high-level but resumable state, rather than std::terminate() or segfault.

How should I best customise these accessors while maintaining the robustness of shared_ptr? It seems that encapsulating shared_ptr in a throwing_shared_ptr may be the best option, but I'm wary of breaking the magic. Am I best off copying the Boost source and just changing the ASSERTs to an appropriate throw statement?


The actual type name used everywhere for the appropriate smart_ptr<T> type is a typedef expanded from a macro; i.e. ForwardDeclarePtr(Class) expands to something like:

class Class;
typedef boost::smart_ptr<Class> ClassPtr;

Everything passes, takes, or stores a ClassPtr - so I can replace the underlying type pretty freely; and I suspect this alleviates the potential slicing/hiding issue.


回答1:


There's really no "magic" in std::shared_ptr<T> that would be removed if you wrapped it inside a custom class that would throw an exception when dereferencing a NULL shared pointer. So I don't see why that approach wouldn't work, as long as your new wrapper-class follows all the semantics of the std::shared_ptr<T> type.

BTW, you could also take a slightly different approach, and that is create a wrapper-class that simply won't allow others to pass NULL pointers to the wrapped std::shared_ptr<T> data-member in the first-place. Basically it would be a class that would enforce the std::make_shared<T> idiom in its constructor. I'm not sure, based on the workings of your code if this is possible, but it's another way to circumvent the problem using a RAII approach rather than throwing exceptions.




回答2:


Just subclass std::shared_ptr into throwing_shared_ptr, override those two methods, and have them assert and call through to std::shared_ptr's impl. This should work fine as long as you use throwing_shared_ptr everywhere instead of slicing it to a std::shared_ptr.



来源:https://stackoverflow.com/questions/12452565/customising-stdshared-ptr-or-boostshared-ptr-to-throw-an-exception-on-null-d

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!