防止 std::unique_ptr 的不安全取消引用

Preventing unsafe dereferencing of std::unique_ptr

摘自 cppcon2015 的幻灯片:

unique_ptr<A> f() {
   auto a = make_unique<A>();
   return a;
}

//Why does this even compile?
const A & dangling = *f(); 

//BOOM!!!
use(dangling);

我的问题是:*this 的右值引用可以解决吗?

我在 cppreference 的规范中看到:

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

问题:

  1. 禁止 operator* 用于右值 unique_ptr 并且仅取消引用对左值 unique_ptr 有效是否有意义?
  2. 仍然有有效的用例来保持右值 unique_ptr 可取消引用?

像这样:

//Make sure it is an lvalue.
typename std::add_lvalue_reference<T>::type operator*() const &;

注意:我不确定语法或正确性,我对 *this 的右值引用没有经验。

My question is: with rvalue references for *this, can this be solved?

技术上是的。一种解决方案是为右值引入一个额外的(删除的)重载:

typename std::add_lvalue_reference<T>::type operator*() const&& = delete;
//                                                      ~~~~~~~~~~~~~~~^

并通过添加引用限定符来修改现有的:

typename std::add_lvalue_reference<T>::type operator*() const&;
//                                                         ~~^~~

由于右值强烈倾向于被右值引用绑定,任何试图取消引用涉及 unique_ptr 的右值表达式都会导致编译错误 - "use of deleted function".

Would it make sense to disallow operator* for rvalue unique_ptrs and only have dereference valid for lvalue unique_ptrs?

不总是。因此,我怀疑图书馆是否应该对 unique_ptr 规范施加额外的限制,只是为了防止可能的误用。

There are still valid use cases to keep the rvalue unique_ptr dereferenceable?

临时文件的生命周期在临时文件所属的完整表达式结束时结束。这意味着只要关联的 unique_ptr 还存在,通过取消引用 unique_ptr 获得的对象就是有效的,因此下面的用例是有效的,如果 operator* 则不可能右值被禁用:

(*f()).foo();
//          ^~~ unique_ptr is destroyed here


use(*f());
//       ^~~ unique_ptr is destroyed here