unique_ptr 让人头疼的设计

design headache with unique_ptr

假设我们有 class Foo:

class Foo {
public:
  ...
};

Foo 有一个实例方法,可以将 Foo 实例转换为另一个 Foo 实例,或者 returns 相同的 Foo 实例:

<some appropriate pointer type to Foo> Foo::tryToTransform() {
  if (canBeTransformed()) {
    <delete this Foo instance>;
    return <new instance of Foo>;
  }
  else {
    return <this instance of Foo>;
  }
}

客户代码:

<some appropriate pointer type to Foo> foo = ...;
...
foo = foo->tryToTransform();

使用裸指针很容易做到这一点:

Foo* Foo::tryToTransform() {
  if (canBeTransformed()) {
    delete this;
    return new Foo(...);
  }
  else {
    return this;
  }
}

Foo* foo = ...;
...
foo = foo->tryToTransform();

但是如果客户端代码使用 unique_ptr 而不是裸指针呢?也就是说,理想情况下我希望客户端代码如下所示:

unique_ptr<Foo> foo = ...;
...
foo = foo->tryToTransform();

如何定义 Foo::tryToTransform() 以启用此类(或类似)客户端代码?

因为您的 tryToTransform 函数是一个 成员函数 ,调用者保留 unique_ptr 的所有权。因此,不可能(没有肮脏的技巧)从成员函数内部删除调用者的 unique_ptr

因此,您需要一个获取unique_ptr:

所有权的静态函数
class Foo {
    static unique_ptr<Foo> tryToTransform(unique_ptr<Foo> ptr) {
        if(...) {
            return unique_ptr<Foo>(new Foo()); // old ptr is destroyed
        } else {
            return ptr;
    }
};

调用为

unique_ptr<Foo> foo = ...;
...
foo = Foo::tryToTransform(move(foo));

这通过让 tryToTransform 获得 unique_ptr 的所有权来实现。然后它就可以随心所欲地销毁指针。