unique_ptr::get() 而不是 &* 是怎么回事?

What's with unique_ptr::get() instead of &*?

本文关键字:怎么回事 ptr get unique      更新时间:2023-10-16

我使用unique_ptr来管理一些资源,以便在各种情况下安全销毁,等等。

void do_something(BLOB* b);
unique_ptr<BLOB> b(new_BLOB(20));

&*比get差得多吗?例如

do_something(&*b);

do_someting(b.get());

两者似乎都有效。

如果unique_ptr没有内存,则std::unique_ptroperator*具有未定义的行为,其中get()将返回nullptr

如果unique_ptr可能是空的,我建议使用get(),否则没有区别。

&*b不一定等同于b.get()。为了确保接收到指向托管对象的指针,您需要使用get()。有两个原因:

  • 在不管理任何对象的unique_ptr上调用operator*是未定义的行为
  • 类型为T的托管对象可能会重载operator&,因此您可能不会收到指向T的有效指针

本标准定义了std::unique_ptr:中operator*的组合

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

  1. 需要:get() != nullptr

  2. 返回:*get()

因此,如果get()返回nullptr,则不允许应用operator*(来自&*)。

您将获得托管对象中任何重载的operator&的返回值(如果存在)。这可以通过使用std::addressof来避免,但未定义的行为问题仍然存在。

std::unique_ptr<T>::get()将为您提供托管对象的地址,如果没有托管对象,则为nullptr。使用get()更安全,并且可以得到可预测的结果。

正如其他答案所指出的,如果unique_ptr不管理任何对象,则使用&*会导致未定义的行为。

对于unique_ptr管理指针的情况,在大多数情况下,

do_something(&*b);

相当于

do_someting(b.get());

如果BLOB有一个operator&重载,它返回的指针与对象的地址不同,那么唯一可以得到不同结果的情况就是。

这实际上是一个基于意见的问题。

我碰巧觉得&*ptr看起来很难看,读者不清楚它为什么会这样写。但它的优点是可以与智能指针和常规指针配合使用。