类成员中unique_ptr的正确用法

问题描述 投票:0回答:4

我正在尝试真正从 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;
}
c++ c++11 c++14 unique-ptr
4个回答
19
投票

你的代码工作正常(虽然多余的*

move
可以省略),但最好尽早构造
unique_ptr

class 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()
    表达式的结果已经是右值了。

5
投票

这是正确的用法吗?

除了

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

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

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

如果初始化抛出异常,这可以防止

temp
泄漏,并使工厂的用户更难意外泄漏返回的指针。


1
投票

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

在标题中。

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;
}

0
投票

另外,我想补充一点,您可能需要为您的类定义复制构造函数和赋值运算符。

我使用了此类的向量,

std::vector<MyClass>
,并遇到了问题。当您想到这一点时,感觉很明显,因为如果需要重新定位,
vector
需要一种方法来复制数据。您不能简单地复制
unique_ptr
成员,因此需要为包含智能指针的类编写复制构造函数。

我编写了一个非常量复制构造函数来移动指针来解决我的问题。

© www.soinside.com 2019 - 2024. All rights reserved.