为什么 gsl::not_null 确保 get() 上的 ptr 不为 null?

ale*_*in0 6 c++ null cpp-core-guidelines guideline-support-library

在微软实施指南支持库中我看到以下代码:

template<class T>
class not_null {
    ...
    template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
    constexpr explicit not_null(U&& u) : ptr_(std::forward<U>(u)) {
        Expects(ptr_ != nullptr);
    }
    ...
    constexpr T get() const {
        Ensures(ptr_);
        return ptr_;
    }
    ...
    T ptr_;
}
Run Code Online (Sandbox Code Playgroud)

所有gsl::not_null可能采用指针的构造函数都会检查这些指针是否为空,但我们仍然在每次ptr_取消引用时检查指针 ( ) 的存储值是否为空。鉴于在 C++ 中我们通常不会为不需要的东西付费,为什么我们要进行此检查?

UP:确保按如下方式实现(使用默认标志):

#define GSL_LIKELY(x) (!!(x))
...
#define GSL_CONTRACT_CHECK(type, cond)                         \
(GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate())
...
#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)
Run Code Online (Sandbox Code Playgroud)

小智 4

这些评论已经给出了为什么删除空检查not_null::get()是不可取的想法。主要问题是该更改允许在移动后取消引用智能指针。

例如,请参阅以下有关 PR 的讨论,该 PR 允许使用not_null<unique_ptr>以及更改如何与删除空检查不兼容not_null::get()

https://github.com/Microsoft/GSL/pull/675

至于性能问题,编译器优化器应该能够删除许多空检查,但当然不是全部。如果某些检查没有删除但似乎可以删除,我们应该修复编译器优化。