将 std::vector<std::unique_ptr<T>> 的所有权传递给类构造函数

Pass ownership of std::vector<std::unique_ptr<T>> to class constructor

提问人:Mr. Boy 提问时间:11/7/2023 最后编辑:Ted LyngmoMr. Boy 更新时间:11/7/2023 访问量:95

问:

现有工厂方法生成std::vector<std::unique_ptr<MyType>>

我想将其传递给一个新类的构造函数,该构造函数将获得对象的所有权,因此向量的元素在类对象销毁时被销毁。

std::vector<std::unique_ptr<MyType>> vec = ...;
std::unique_ptr<MyClass> mc = new MyClass(vec);
return mc;

class MyClass
{
 public:
  MyClass(std::vector<std::unique_ptr<MyType>> &vec)
  {
    // ???????
  }

 private:
  std::vector<std::unique_ptr<MyType>> m_vec;
};

但显然,原件“拥有”了这些物品,它们将被摧毁。vecMyType

改变这种状况的最佳方法是什么?我真的不想离开,我想向未来的开发人员明确表示,这是矢量的所有者。unique_ptrMyClass

C++ 构造函数

评论

1赞 Osyotr 11/7/2023
MyClass(std::vector<std::unique_ptr<MyType>> vec) + m_vec(std::move(vec))和?std::make_unique<MyClass>(std::move(vec));
0赞 273K 11/7/2023
如果不显示用法,则不太可能回答问题。描述非常模糊,使用代码会更清晰。您可以将每个向量元素移动到一个新的向量中,也可以将整个向量...
0赞 Pepijn Kramer 11/7/2023
您是真的想将向量移动到 MyClass 中,还是想要一个可以创建 MyType 的多个实例的构造函数。如果是这样,所有实例都需要相同的构造函数参数还是每个实例需要不同的构造函数参数?

答:

6赞 Ted Lyngmo 11/7/2023 #1

最简单的方法可能是模仿移动构造函数的作用并使用右值引用:

class MyClass {
public:
    MyClass(std::vector<std::unique_ptr<MyType>>&& vec)
//                                              ^^
        : m_vec(std::move(vec)) {}
//              ^^^^^^^^^^^^^^

private:
    std::vector<std::unique_ptr<MyType>> m_vec;
};

您现在可以将这样的 a 移动到 :vectorMyClass

int main() {
    std::vector<std::unique_ptr<MyType>> vec;

    MyClass mc(std::move(vec));
}

如果您不熟悉移动语义,这里有一个示例,说明它的用途。有关详细信息,请参阅五法则

class MemoryHog {
public:
    // default ctor, hogging a lot of memory:
    MemoryHog() : m_ptr(new char[1024 * 1024 * 1024]) {}

    // copy ctor, hogging memory and copies:
    MemoryHog(const MemoryHog& other) : m_ptr(new char[1024 * 1024 * 1024]) {
        std::copy_n(other.m_ptr, 1024 * 1024 * 1024, m_ptr);
    }

    // move ctor, doesn't allocate but instead steals the pointer from the
    // object being moved from:
    MemoryHog(MemoryHog&& other) noexcept :
        m_ptr(std::exchange(other.m_ptr, nullptr)) {}

    // copy assignment operator + move assignment operator be here too

    ~MemoryHog() {
        delete[] m_ptr;
    }

private:
    char* m_ptr;
};

评论

0赞 Mr. Boy 11/7/2023
作为一个老派的 c++ 开发人员,我落后于时代......移动 CTOR 对我来说不是很熟悉 - 谢谢!
0赞 Ted Lyngmo 11/7/2023
@Mr.Boy 这是自 C++11 以来的新酷事物:-)移动构造函数值类别可能会引起人们的兴趣
0赞 Ted Lyngmo 11/7/2023
@Mr.Boy:我添加了一个小例子,说明如何编写新类以利用移动语义。
1赞 Ben Voigt 11/7/2023
@Mr.Boy:移动构造函数(和移动赋值)解决了所有问题(给了我们std::auto_ptrstd::unique_ptr)