1

我正在学习std::unique_ptr,试图了解它代表什么。

给定一个返回 a 的函数(不受我控制)unique_ptr,是否暗示/很好理解每次调用都返回unique_ptr指向新对象的 a (不同于任何先前的调用)?

unique_ptr举例来说,下面的代码在退出时产生一个双释放,我希望我能正确理解为什么:因此unique_ptr封装相同内存/对象的两个 s 会导致第二个被破坏时双重释放。因此,以下函数的实现是否会getUniquePtr()被普遍/隐含地理解为不合理?

// main.cpp
#include <memory>
#include <iostream>

std::unique_ptr<int> getUniquePtr() {
  static int* p = new int(42);
  return std::unique_ptr<int>(p);
}

class PtrOwner {
public:
  std::unique_ptr<int> p_;
};

int main( int argc, char* argv[] ) {
  PtrOwner po1;
  PtrOwner po2;
  po1.p_ = getUniquePtr();
  po2.p_ = getUniquePtr();

  return 0;
}
4

2 回答 2

5

应该假设,如果一个函数返回std::unique_ptr<T>,则返回的智能指针指向一个当前未被任何其他人管理的对象。这并不一定意味着它总是指代不同的对象。只要遵循这个约定,就可以避免双重释放错误。如果违反了这个约定,就会出现双释放错误。

例如,如果你看到这样的函数:

std::unique_ptr<T> foo(std::unique_ptr<T> arg);

在某些情况下,此函数可能会返回std::move(arg),或者它可能会破坏arg并返回一些其他指针。(您必须阅读文档才能知道它的作用)。这意味着您可以执行以下操作:

auto t = std::make_unique<T>();
t = foo(std::move(t));
t = foo(std::move(t));

在这种情况下,foo可能只返回两次相同的指针值,这是非常安全的。这个例子看起来很傻,但希望它能理解我的意思。

于 2020-12-02T20:22:41.723 回答
2

是的,您的假设(大部分)是正确的。Aunique_ptr独占该对象,这意味着unique_ptr在任何给定时间,任何两个 s 都不应该指向同一个对象。

正如其他人指出的那样,这并不能保证对同一函数的多次调用会返回不同的对象。这是因为您可以传递所有权(通过移动它),所以如果您将所有权传递回一个函数,就像 Brians 的回答一样,它很可能会再次返回相同的对象,而不会破坏任何规则。

如果您决定使用智能指针来管理对象,请尽量避免使用 new 和 delete。要创建由 a 拥有的对象 T unique_ptr,请使用make_unique<T>unique_ptr这避免了为同一个对象创建多个的错误。unique_ptr正是由于这个原因,A是不可复制的。换句话说,您的 getUniquePtr 应该这样实现:

return std::make_unique<int>(42);

从原始指针(而不是使用 make_unique)构造智能指针的少数原因之一是当您有现有代码或使用原始指针的库时,您无法更改。

于 2020-12-02T22:04:36.270 回答