gpt4 book ai didi

c++ - 为什么 std::unique_ptr operator* 抛出而 operator-> 不抛出?

转载 作者:可可西里 更新时间:2023-11-01 18:40:00 25 4
gpt4 key购买 nike

在 C++ 标准草案 (N3485) 中,它声明如下:

20.7.1.2.4 unique_ptr 观察者 [unique.ptr.single.observers]

typename add_lvalue_reference<T>::type operator*() const;

1 Requires: get() != nullptr.
2 Returns: *get().

pointer operator->() const noexcept;

3 Requires: get() != nullptr.
4 Returns: get().
5 Note: use typically requires that T be a complete type.

你可以看到operator* (取消引用)未指定为 noexcept ,可能是因为它会导致段错误,但随后 operator->在同一对象上指定为 noexcept .两者的要求相同,但异常规范有所不同。

我注意到它们有不同的返回类型,一种返回指针,另一种返回引用。那是说 operator->实际上并没有取消引用任何东西?

事实是使用operator->在任何类型的 NULL 指针上,都会发生段错误(是 UB)。那么,为什么将其中之一指定为 noexcept而另一个不是?

我确定我忽略了一些东西。

编辑:

查看std::shared_ptr我们有这个:

20.7.2.2.5 shared_ptr 观察者 [util.smartptr.shared.obs]

T& operator*() const noexcept;

T* operator->() const noexcept;

不一样?这与不同的所有权语义有什么关系吗?

最佳答案

段错误在 C++ 的异常系统之外。如果您取消引用一个空指针,则不会抛出任何类型的异常(好吧,至少如果您遵守 Require: 子句;请参阅下面的详细信息)。

对于 operator->,它通常简单地实现为 return m_ptr;(或 return get(); 对于 unique_ptr)。如您所见,运算符本身不能抛出 - 它只是返回指针。没有取消引用,什么都没有。该语言对 p->identifier 有一些特殊的规则:

§13.5.6 [over.ref] p1

An expression x->m is interpreted as (x.operator->())->m for a class object x of type T if T::operator->() exists and if the operator is selected as the best match function by the overload resolution mechanism (13.3).

以上递归应用,最后必须产生一个指针,为此使用内置的 operator->。这允许智能指针和迭代器的用户简单地执行 smart->fun() 而无需担心任何事情。

规范的 Require: 部分注释:这些表示先决条件。如果你不满足他们,你就是在调用 UB。

Why then, is one of these specified as noexcept and the other not?

老实说,我不确定。似乎取消引用指针应该始终是 noexcept,但是,unique_ptr 允许您完全更改内部指针类型是什么(通过删除器)。现在,作为用户,您可以为 pointer 类型的 operator* 定义完全不同的语义。也许它可以即时计算东西?所有这些有趣的东西,可能会抛出。


Looking at std::shared_ptr we have this:

这很容易解释 - shared_ptr 不支持上述对指针类型的自定义,这意味着内置语义始终适用 - 和 *p 其中 pT* 根本不会抛出。

关于c++ - 为什么 std::unique_ptr operator* 抛出而 operator-> 不抛出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21653352/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com