【问题标题】:Why gsl::not_null ensures ptr is not null on get()?为什么 gsl::not_null 确保 ptr 在 get() 上不为空?
【发布时间】:2018-07-03 15:12:59
【问题描述】:

在 Microsoft implementation 的指南支持库中,我看到以下代码:

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_;
}

gsl::not_null 的所有构造函数都可能会检查这些指针是否为空,但我们仍会在 each 取消引用时检查指针 (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)

【问题讨论】:

  • 我看到在讨论中记得一些关于该检查的内容应该只在 std::unique_ptr 专业化中,以确保 not null std::unique_ptr 在被取消引用后不会被取消引用移自。不过我还是不喜欢。
  • @FrançoisAndrieux,请参阅有关Ensures 实施的更新。实际上,这取决于标志,我附上了默认标志。据我了解,它实际上在运行时需要一些成本
  • 允许移动not_null(not_null&amp;&amp; other) = default;是原因。也许它应该是不可移动的“not_null” - 或者一些更复杂的解决方案 - 因为它现在正在实施 - 我怀疑我会使用它
  • @PiotrNycz,实际上,就我在标准中看到的而言,移动的对象处于未指定但有效的状态。实验表明指针值在移动时不会改变。
  • 查看github.com/Microsoft/GSL/pull/449中的讨论。

标签: c++ null cpp-core-guidelines guideline-support-library


【解决方案1】:

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

例如,请参阅以下关于启用 not_null&lt;unique_ptr&gt; 的 PR 的讨论以及更改与从 not_null::get() 中删除空检查的不兼容情况

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

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

【讨论】:

  • std::shared_ptr 怎么样?我认为规范要求 std::move() 也使原件无效?
猜你喜欢
  • 1970-01-01
  • 2021-04-29
  • 1970-01-01
  • 1970-01-01
  • 2016-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多