[英]Safe pointer dereferencing in C++
在我们的代码库中,我们有许多类似以下的构造:
auto* pObj = getObjectThatMayVeryRarelyBeNull();
if (!pObj) throw std::runtime_error("Ooops!");
// Use pObj->(...)
在99.99%的情况下,不会触发此检查。 我正在考虑以下解决方案:
auto& obj = deref_or_throw(getObjectThatMayVeryRarelyBeNull());
// Use obj.(...)
其中deref_or_throw
声明如下:
template<class T> T& deref_or_throw(T* p) {
if (p == nullptr) { throw std::invalid_argument("Argument is null!"); }
return *p;
}
该代码更加清晰,可以根据需要运行。
问题是:我是否正在重新发明轮子? 标准或增强中是否有相关解决方案? 或者您对解决方案有何评论?
PS。 相关问题(答案不令人满意): 是否有C ++等效于NullPointerException
有两种方法可以处理“空指针的罕见情况”问题。 首先,它是建议的异常解决方案。 为此,方法deref_or_throw
是一件好事,尽管我宁愿抛出runtime_error
,而不是invalid_argument
异常。 如果您愿意,也可以考虑将其命名为NullPointerException
。
但是,如果ptr != nullptr
情况实际上是该算法的前提条件,则应尽最大努力使该非null情况达到100%的安全性。 在这种情况下, assert
是适当的事情。
assert
优点:
assert
缺点:
您还应该考虑编写一种方法getObjectThatMayNeverBeNullButDoingTheSameAsGetObjectThatMayVeryRarelyBeNull()
:该方法保证可以返回指向对象的非null指针,否则该指针与原始方法完全等效。 但是,如果可以加倍努力,我强烈建议无论如何不要返回原始指针。 拥抱C ++ 11并按值返回对象:-)
您可以并且可能应该在设计时考虑到null
例。 例如,在您的问题域中,类方法何时返回null
才有意义? 什么时候使用null
参数调用函数有意义?
广义上讲,只要有可能,从代码中删除null
引用都是有益的。 换句话说,您可以对不变量进行编程,使其“此处或此处都不为空”。 这有很多好处。 您无需通过将方法包装在deref_or_throw
来混淆代码。 您可能会从代码中获得更多的语义含义,因为在现实世界中事物多长时间为null
? 如果您使用异常来表示错误而不是null
值,则代码可能更具可读性。 最后,您减少了错误检查的需要,并降低了运行时错误(可怕的空指针取消引用)的风险。
如果您的系统在设计时没有考虑到null
情况,那么我想说最好deref_or_throw
, 不要用deref_or_throw
疯狂地包装所有deref_or_throw
。 也许采取敏捷方法。 在编写代码时,请检查您的类对象作为服务提供的合同。 可以合理预期这些合同多久返回一次null
? 在这些情况下null
的语义值是什么?
您可能会确定系统中可能合理预期返回null
。 对于这些类, null
可能是有效的业务逻辑,而不是指示实现错误的边缘情况。 对于可能期望返回null
,额外的检查可能是值得的。 从这个意义上讲,检查null
更像是业务逻辑,而不是底层实现细节。 但是,将所有指针deref_or_throw
系统地包装在deref_or_throw
可能是一种解决方法,这本身就是毒药。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.