Ton*_*ion 34 c++ language-lawyer c++11
在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.
Run Code Online (Sandbox Code Playgroud)
您可以看到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;
Run Code Online (Sandbox Code Playgroud)
这是不一样的?这与不同的所有权语义有什么关系吗?
Xeo*_*Xeo 26
段错误不在C++的异常系统中.如果取消引用空指针,则不会抛出任何类型的异常(嗯,至少如果您遵守该Require:条款;请参阅下面的详细信息).
因为operator->,它通常简单地return m_ptr;(或return get();为unique_ptr)实现.如您所见,操作符本身不能抛出 - 它只返回指针.没有解除引用,没有任何东西.该语言有一些特殊规则p->identifier:
§13.5.6 [over.ref] p1
表达式
x->m被解释为类型为if(x.operator->())->m的类对象x,T如果T::operator->()操作符被重载决策机制选为最佳匹配函数(13.3).
以上适用于递归,最后必须产生一个指针,使用内置指针operator->.这允许智能指针和迭代器的用户完全smart->fun()不用担心任何事情.
说明Require:部分的注释:这些表示前提条件.如果你不满足他们,你就是在调用UB.
那么,为什么其中一个指定为noexcept而另一个不指定?
说实话,我不确定.这似乎是解引用指针应始终noexcept,然而,unique_ptr让您彻底改变内部指针类型是(通过删除器)的东西.现在,作为用户,您可以为operator*您的pointer类型定义完全不同的语义.也许它会在飞行中计算出来的东西?所有有趣的东西,可能会抛出.
看看std :: shared_ptr我们有这个:
这很容易解释- shared_ptr不支持上述定制指针类型,这意味着内置的语义总是适用-和*p那里p是T*根本不会抛出.
| 归档时间: |
|
| 查看次数: |
3912 次 |
| 最近记录: |