C ++中的安全指针解除引用

时间:2015-03-18 12:35:38

标签: c++ exception nullpointerexception dereference

在我们的代码库中,我们有许多这样的结构:

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。相关问题(没有令人满意的答案):Is there a C++ equivalent of a NullPointerException

2 个答案:

答案 0 :(得分:4)

有两种方法可以处理&#34;空指针的罕见情况&#34;问题。首先,它是建议的异常解决方案。为此,方法deref_or_throw是一件好事,但我更倾向于抛出runtime_error而不是invalid_argument例外。如果您愿意,也可以考虑将其命名为NullPointerException

但是,如果ptr != nullptr案例实际上是算法的前提条件,那么您应该尽量在这种非空案例中实现100%的安全性。在这种情况下,assert是合适的。

assert的优点:

  • 在发布模式下运行时无成本
  • 让开发人员清楚明白,他对此事负责,永远不会发生。

assert的缺点:

  • 发布模式中潜在的未定义行为

您还应该考虑编写方法getObjectThatMayNeverBeNullButDoingTheSameAsGetObjectThatMayVeryRarelyBeNull():一种方法,可以保证返回一个非空指针,该指针与对象完全等效于原始方法。但是,如果你可以加倍努力,我强烈建议不要再返回原始指针。包含C ++ 11并按值返回对象: - )

答案 1 :(得分:1)

您可以并且可能应该考虑null个案例。例如,在您的问题域中,何时返回null类方法是否有意义?何时用null参数调用函数是否有意义?

从广义上讲,尽可能从代码中删除null引用会很有用。换句话说,你可以编程为不变的&#34;这里不会为空......或者那里&#34;。这有很多好处。您不必通过在deref_or_throw中包装方法来混淆代码。你可以从代码中获得更多的语义含义,因为在现实世界中事物null的频率是多少?如果使用异常来指示错误而不是null值,则代码可能更具可读性。最后,您减少了错误检查的需要,并降低了运行时错误的风险(可怕的空指针取消引用)。

如果您的系统设计时没有考虑null个案例,我说它最好不要管它,疯狂地用{包裹一切{1}}。也许采取敏捷方法。在编写代码时,请检查类对象提供的服务合同。这些合同多久可以合理地返回deref_or_throw?在这些情况下null的语义值是多少?

您可能会识别系统中可能合理预期返回null的类。对于这些类,null可能是有效的业务逻辑,而不是指示实现错误的边缘情况。对于可能会返回null的类,附加检查可能值得安全。从这个意义上讲,检查null感觉更像是业务逻辑而不是低级实现细节。但是,在整个董事会中,系统地将所有指针顺序包裹在null中可能是一种治疗方法,也就是它自己的毒药。