【问题标题】:design headache with unique_ptr用 unique_ptr 设计头痛
【发布时间】:2015-10-27 16:04:01
【问题描述】:

假设我们有课程Foo

class Foo {
public:
  ...
};

Foo 有一个实例方法,可以将Foo 实例转换为另一个Foo 实例,或者返回相同的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() 以启用此类(或类似)客户端代码?

【问题讨论】:

  • 哎呀! delete this 是一个糟糕的想法。让你的转换方法成为一个静态方法,你所有的麻烦都会消失。
  • 此外,我认为这仅适用于更改对象类型,即将X的实例转换为Y的实例。否则,你为什么要删除并重新创建对象?
  • @nneonneo 1. 我不是delete this 的粉丝,但在某些情况下没关系 - 例如,请参阅this FAQ article 2. 使Foo::tryToTransform() 静态有助于@987654339以任何方式@问题?
  • @el.pescado 重点是tryToTransform(),什么时候可以转换Foo实例,把它转换成另一个具有不同状态的实例。 (Foo 类确实有状态,虽然我没有在人为的代码 sn-p 中明确显示。)
  • 您可以强制对象进入不同的状态,而无需分配它的新实例。

标签: c++ c++11 factory unique-ptr


【解决方案1】:

因为您的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 的所有权来工作。然后它可以随意销毁指针。

【讨论】:

    猜你喜欢
    • 2019-02-11
    • 2011-03-19
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    • 2012-09-07
    • 2015-09-18
    • 1970-01-01
    相关资源
    最近更新 更多