【问题标题】:"No-throw dereferencing" of std::unique_ptrstd::unique_ptr 的“无抛出取消引用”
【发布时间】:2014-08-21 20:02:49
【问题描述】:

我用 C++ 编写代码,它使用 std::unique_ptr u 来处理 std::string 资源,我想取消引用 u 以便可以将 std::string 传递给 std::string 复制构造函数的调用:

std::string* copy = new std::string( /*dereference u here*/ );

我知道newstd::string 复制构造函数可能会抛出,但这不是我的意思。我只是想知道取消引用u 是否已经引发异常。我觉得奇怪的是operator*没有标记为noexcept,而std::unique_ptr 方法get 实际上标记为noexcept。换句话说:

*( u.get() )

整体是noexcept

*u

不是。这是标准的缺陷吗?我不明白为什么会有不同。有什么想法吗?

【问题讨论】:

  • *(u.get()) noexcept 怎么样? u.get()不能返回nullptr吗?
  • @BartoszKP 返回的nullptrnoexcept 有什么关系?
  • @BartoszKP:嗯,cplusplus.com 上的引用说 get 是 noexcept ...据我所知,取消引用 nullptr 不会引发异常。无论如何,我在尝试取消引用之前检查 if( u )。
  • @Slava 是的,你是对的。我的意思是operator* 可以验证您是否正在取消引用空指针,如果是则抛出,而get() 不应该这样做。但这仍然没有意义,因为 operator->noexcept...
  • cppreference.com 说operator* 可能会抛出,让我们看看标准怎么说

标签: c++ c++11 unique-ptr


【解决方案1】:

unique_ptr::operator*() 可能涉及对您存储在unique_ptr 中的类型的operator*() 重载的调用。注意unique_ptr 中存储的类型不必是裸指针,您可以通过嵌套类型D::pointer 更改类型,其中Dunique_ptr 的删除器的类型。这就是函数不是noexcept的原因。

此警告不适用于您的用例,因为您将 std::string * 存储在 unique_ptr 中,而不是某些重载 operator* 的类型。所以你的电话实际上是noexcept

【讨论】:

  • 可以标记为noexcept(noexcept(*std::declval<T>())) 吗?
  • @RyanHaining 这可能适用于我描述的边缘情况,但如果T 是一个指针呢?现在你在noexcept 规范中得到了nullptr 的尊重。
  • 我没有意识到 operator* 与 *( .get() ) 相比在底层如此复杂。非常有趣,感谢您详细说明!
  • 如果Tnullptr_t,表达式仍然没有被实际计算,我想我不明白你的意思
  • 另外,不创建operator * noexcept 允许实现通过在调试模式下抛出异常来诊断UB(如果存储的指针为空)。
猜你喜欢
  • 2023-03-23
  • 2015-12-20
  • 2019-10-29
  • 1970-01-01
  • 2013-02-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多