在类成员中正确使用unique_ptr

时间:2017-03-04 11:31:13

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

我试图真正从c ++ 98转向c ++ 11及更新版本。我已经把头脑包裹在大部分新东西上,但我仍然不确定unique_ptr的正确用法。

考虑下面的例子,其中A类有一个unique_ptr成员(我之前会使用原始指针!)。当用户需要时,应该通过在其他地方调用函数(不是类的一部分)来分配此成员变量。这是正确的用法吗?如果没有,最好的选择是什么?

class A {
private:
   unique_ptr<MyType> mt;
public:
   void initStuff() {
      mt.reset(std::move(StaticFuncSomewhereElese::generateMyType()));
   } 
};

MyType* StaticFuncSomewhereElese::generateMyType() {
    MyType* temp = new MyType(...);
    //do stuff to temp (read file or something...)
    return temp;
}

3 个答案:

答案 0 :(得分:3)

您的代码工作正常(尽管可以省略冗余的* move),但最好尽早构建unique_ptr

classss A {
private:
   std::unique_ptr<MyType> mt;
public:
   void initStuff() {
      mt = StaticFuncSomewhereElese::generateMyType();
   } 
};

std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType() {
    auto temp = std::make_unique<MyType>(…);
    // `make_unique` is C++14 (although trivially implementable in C++11).
    // Here's an alternative without `make_unique`:
    // std::unique_ptr<MyType> temp(new MyType(…));

    //do stuff to temp (read file or something...)
    return temp;
}

很明显,调用者必须删除generateMyType的返回值,并且内存泄漏的可能性较小(例如,如果generateMyType提前返回)。

* move是多余的,因为:

  1. 无法移动原始指针。
  2. 无论如何generateMyType()表达式的结果已经是右值。

答案 1 :(得分:3)

  

这是正确的用法吗?

std::move多余外,是的,这是正确的。这是多余的,因为a)裸指针被复制,无论它们是左值还是右值,b)函数不返回引用,因此返回值已经是右值,因此不需要转换。

但还有改进的余地。特别是,我建议从工厂函数返回一个唯一的指针:

std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType()

如果初始化抛出异常,这会阻止temp泄漏,并使工厂用户更难以意外泄漏返回的指针。

答案 2 :(得分:0)

为什么不将其设为通用模板工厂?

在标题中。

template <typename T>
std::unique_ptr<T> generateMyType();

classss A {
private:
   std::unique_ptr<MyType> mt;
   std::unique_ptr<MyOtherType> mot;
public:
   void initStuff() {
      mt = generateMyType<MyType>();
      mot = generateMyType<MyOtherType>();
   } 
};

在源文件中

template <typename T>
std::unique_ptr<T> generateMyType()
{
  auto temp = std::make_unique<T>();
  return temp;
}