本文介绍了为什么std :: unique_ptr operator * throw和operator->不抛?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In the C++ standard draft (N3485), it states the following:

20.7.1.2.4 unique_ptr observers [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 ,可能是因为它可能导致segfault,但是在 operator-> 对象被指定为 noexcept 。

You can see that operator* (dereference) is not specified as noexcept, probably because it can cause a segfault, but then operator-> on the same object is specified as noexcept. The requirements for both are the same, however there is a difference in exception specification.

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

I have noticed they have different return types, one returns a pointer and the other a reference. Is that saying that operator-> doesn't actually dereference anything?

事实是,在任何类型的指针为NULL的情况下使用 operator-> ,将segfault(是UB)。为什么,是这些之一指定为 noexcept ,另一个不是?

The fact of the matter is that using operator-> on a pointer of any kind which is NULL, will segfault (is UB). Why then, is one of these specified as noexcept and the other not?

编辑:

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

20.7.2.2.5 shared_ptr observers [util.smartptr.shared.obs]

20.7.2.2.5 shared_ptr observers [util.smartptr.shared.obs]

T& operator*() const noexcept;

T* operator->() const noexcept;

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

It's not the same? Does that have anything to do with the different ownership semantics?

推荐答案

segfault不在C ++的异常系统之外。如果你解引用一个空指针,你不会得到任何类型的异常抛出(如果你遵守 Require:子句,请参见下面的细节)。

A segfault is outside of C++'s exception system. If you dereference a null pointer, you don't get any kind of exception thrown (well, atleast if you comply with the Require: clause; see below for details).

对于 operator-> ,它通常简单地实现 return m_ptr; (或 return get(); for unique_ptr )。正如你所看到的,运算符本身不能抛出 - 它只是返回指针。没有解引用,没有什么。该语言对 p>标识符有一些特殊规则:

For operator->, it's typically implemented as simply return m_ptr; (or return get(); for unique_ptr). As you can see, the operator itself can't throw - it just returns the pointer. No dereferencing, no nothing. The language has some special rules for p->identifier:

§13.5。 6 [over.ref] p1

上述应用递归地并且最终必须产生一个指针,其中使用内置的 operator-> 。这允许智能指针和迭代器的用户只需做 smart-> fun(),而不用担心任何事情。

The above applies recursively and in the end must yield a pointer, for which the built-in operator-> is used. This allows users of smart pointers and iterators to simply do smart->fun() without worrying about anything.

Require:部分规范的注释:这些表示前提条件。

A note for the Require: parts of the specification: These denote preconditions. If you don't meet them, you're invoking UB.

说实话,我不确定。看起来,取消引用指针应始终为 noexcept ,但是 unique_ptr 可以完全更改内部指针类型是什么(通过deleter)。现在,作为用户,您可以在指针类型上为 operator * 定义完全不同的语义。也许它在飞行中计算的东西?所有有趣的东西,可能会抛出。

To be honest, I'm not sure. It would seem that dereferencing a pointer should always be noexcept, however, unique_ptr allows you to completely change what the internal pointer type is (through the deleter). Now, as the user, you can define entirely different semantics for operator* on your pointer type. Maybe it computes things on the fly? All that fun stuff, which may throw.

这很容易解释 - shared_ptr 上述对指针类型的定制,这意味着内置语义始终应用 - 和 * p 其中 p 是 T * 根本不会丢。

This is easy to explain - shared_ptr doesn't support the above-mentioned customization to the pointer type, which means the built-in semantics always apply - and *p where p is T* simply doesn't throw.

这篇关于为什么std :: unique_ptr operator * throw和operator-&gt;不抛?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 07:46