不好的做法,像所有权语义返回unique_ptr的原始指针?

我写了一个静态工厂方法,返回从另一个数据对象填充新的Foobar对象。 我最近一直痴迷于所有权语义,并想知道是否通过让这个工厂方法返回一个unique_ptr传递正确的消息。

 class Foobar { public: static unique_ptr<Foobar> factory(DataObject data); } 

我的意图是告诉客户端代码,他们拥有指针。 没有一个聪明的指针,我只会返回Foobar* 。 但是,我想强制删除这个内存以避免潜在的错误,所以unique_ptr看起来是一个合适的解决scheme。 如果客户端想要延长指针的生命周期,他们只要调用.release()一旦得到unique_ptr

 Foobar* myFoo = Foobar::factory(data).release(); 

我的问题分两部分:

  1. 这种方法是否传达了正确的所有权语义?
  2. 这是一个“坏习惯”返回unique_ptr而不是一个原始指针?

从工厂方法返回一个std::unique_ptr就好了,应该是一个推荐的做法。 它expression的信息是(IMO): 你现在是这个对象的唯一所有者。 此外,为了您的方便,对象知道如何摧毁自己。

我认为这比返回一个原始指针要好得多(客户端必须记住如何处理这个指针)。

不过,我不明白你的意见,关于释放指针延长它的一生。 一般来说,我很less看到有任何理由在智能指针上调用release ,因为我认为指针应该总是由某种RAII结构来pipe理(我称之为release的唯一情况就是将指针放在不同的pipe理数据结构中,例如一个unique_ptr具有不同的删除,我做了一些事情,以保证额外的清理)。

因此,只要客户端需要该对象(或者一个shared_ptr ,如果他们需要多个指针副本),客户端就可以(也应该)简单地将unique_ptr存储在某个地方(例如另一个unique_ptr , 。 所以客户端代码应该看起来更像这样:

 std::unique_ptr<FooBar> myFoo = Foobar::factory(data); //or: std::shared_ptr<FooBar> myFoo = Foobar::factory(data); 

我个人还会为返回的指针types(在本例中为std::unique_ptr<Foobar> )和/或使用的deleter(在本例中为std :: default_deleter)添加一个typedef到工厂对象。 如果以后决定更改指针的分配(因此需要一个不同的方法来销毁指针,它将作为std::unique_ptr的第二个模板参数可见),这样做会更容易。 所以我会做这样的事情:

 class Foobar { public: typedef std::default_deleter<Foobar> deleter; typedef std::unique_ptr<Foobar, deleter> unique_ptr; static unique_ptr factory(DataObject data); } Foobar::unique_ptr myFoo = Foobar::factory(data); //or: std::shared_ptr<Foobar> myFoo = Foobar::factory(data); 

std::unique_ptr唯一拥有它指向的对象。 它说:“我拥有这个东西,没有其他人。”

这正是你想要expression的意思:你说的是“这个function的来电者:你现在是这个对象的唯一所有者;随你做就做,它的一生就是你的责任。

它正确地传递了正确的语义,并且是我认为C ++中的所有工厂都应该工作的方式: std::unique_ptr<T>不强加任何types的所有权语义,而且非常便宜。