C++ 强制使用 unique_ptr 进行动态分配?

C++ force dynamic allocation with unique_ptr?

我发现 unique_ptr 可以指向一个已经存在的对象。 例如,我可以这样做:

class Foo {
public:
  Foo(int nb) : nb_(nb) {}
private:
  int nb_;
};

int main() {
  Foo f1(2);
  Foo* ptr1(&f1);
  unique_ptr<Foo> s_ptr1(&f1);

  return 0;
}

我的问题是:

如果我用 unique_ptr 创建一个 class 作为数据成员(其中 Bar一个 class 复制构造函数被删除的地方)和一个将指针作为参数的构造函数,我可以阻止用户传递一个已经存在的 object/variable 作为参数(在那个构造函数中)(即强迫他使用 new 关键字)? 因为如果他这样做,我将无法保证我的 class 对象的有效状态(用户仍然可以使用 class 之外的地址修改数据成员)..我可以't将Bar的内容复制到另一个内存区。

示例:

class Bar {
public:
  Bar(/* arguments */) { /* data members allocation */ }
  Bar(Bar const& b) = delete;

  /* Other member functions */

private:
  /* data members */
};

class Bar_Ptr {
public:
  Bar_Ptr(Bar* ptr) {
    if (ptr != nullptr) { ptr_ = unique_ptr<Bar> (ptr); }
  } /* The user can still pass the address of an already existing Bar ... */

  /* Other member functions */

private:
  unique_ptr<Bar> ptr_;
};

不,你不能。你不能阻止人们做愚蠢的事情。声明一个模板化函数,returns 一个基于模板化参数的新对象。

我以前见过类似的东西。 诀窍是你创建一个函数(让我们称之为make_unique)接受对象(不是指针,对象,所以可能使用隐式构造函数,它可以"take" class构造函数参数),此函数将创建 return 和 unique_ptr。像这样:

template <class T> std::unique_ptr<T> make_unique(T b);

顺便说一句,你可以推荐别人使用这个功能,但是没有人会强迫他们按照你的推荐去做...

你无法阻止人们做错事。但是你可以鼓励他们做正确的事。或者至少,如果他们做错了事,让它更明显。

例如,使用Bar,不要让构造函数采用裸指针。让它花费 unique_ptrs,按值或按 &&。这样,您就可以强制 caller 创建那些 unique_ptr。您只是将它们移动到您的成员变量中。

那样的话,如果调用者做错了事,错误就在调用者的代码中,而不是你的。

你不能阻止程序员做傻事。 std::unique_ptrstd::shared_ptr 都包含使用现有 ptr 创建实例的选项。我什至见过传递自定义删除器以防止删除的情况。 (对于这些情况,共享 ptr 更优雅)

所以如果你有一个指针,你必须知道它的所有权。这就是为什么我更喜欢使用 std::unique_ptrstd::shared_ptrstd::weak_ptr 作为 'owning' 指针,而原始指针表示非拥有指针。如果您将此传播到创建对象的位置,大多数静态分析器会告诉您您犯了一个错误。

因此,我会将 class Bar_ptr 重写为:

class Bar_ptr {
public:
    explicit Bar_ptr(std::unique_ptr<Bar> &&bar)
        : ptr(std::move(bar)) {}
    // ...
}

由此,您的 class 的 API 强制执行所有权转移,并且由调用者提供有效的 unique_ptr。换句话说,您不必担心传递未分配的指针。

没有人阻止来电者写:

Bar bar{};
Bar_ptr barPtr{std::unique_ptr<Bar>{&bar}};

尽管如果你有一个像样的静态分析器或者甚至只是一个代码审查,我希望这个代码不会被拒绝。