【问题标题】:Is there a way to let "make_unique< T[ ] >" can forward arguments to constructor of T?有没有办法让“make_unique< T[ ] >”可以将参数转发给 T 的构造函数?
【发布时间】:2019-01-29 06:20:18
【问题描述】:

我在一个由 unique_ptr 指向的数组中有一些相同类的对象, 并且每个对象只能使用显式构造函数创建,因为必须将一些参数传递给构造函数。

初始化的时候,我要创建这样一个unique_ptr,如下:

unique_ptr<ClassA [ ] >  arrayA = make_unique<ClassA [ ]>(100, some args to be passed );

但似乎没有任何版本的 make_unique 可以像上面那样做。 根据文档:如果 make_unique 正在制作一个数组,它只需要一个参数,即数组的大小。

我不能在这个场景中使用向量,因为 ClassA 是一个由多个线程(生产者/消费者)共享的消息队列, 而vector会在空间不足时将元素移动到新的地方。

还有另一种方法,我可以在其中创建一个只有显式构造函数的类的数组吗? 同时,我还是想用 unique_ptr 来管理它们。

谢谢!

【问题讨论】:

  • 使用std::vector 来管理它们怎么样?
  • 谢谢。但是我的班级是不可移动的。它实际上是一个消息队列,由生产者和消费者共享。如果空间不足,Vector 会移动元素,但是有多个线程正在读/写队列。所以我不能使用向量。
  • 我真的不明白线程与此有什么关系。在您完成创建它之前,没有线程会访问该数组(否则您有一个严重的设计缺陷)。因此,只需提前创建向量(正如您显然打算在这里做的那样),一旦可用就不要添加或删除元素。
  • std::vectorstd::shared_ptr 怎么样?
  • 如果空间不足,vector 会将元素移动到新位置:如果空间不足,unique_ptr 也有问题。只需在创建线程之前或仅在单个线程中调整向量的大小。

标签: c++ arrays initialization unique-ptr


【解决方案1】:

你不必使用make_unique,你可以构造指针并传递一些手动分配的内存。

class ClassA {
 public:
  int a;
  float b;
};

const auto x = std::unique_ptr<ClassA[]>{new ClassA[2]{{1, 2}, {1, 2}}};

【讨论】:

  • 请考虑 ClassPaire, unique_ptr> xy = XY(new X(), new Y());如果“new X()”成功而“new Y()”失败,是否有机会释放“new X()”分配的内存?所以,我尽可能避免使用“新”。
  • 在我的示例中有一个 unique_ptr 和一个 new。因此它是异常安全的。你想保护一个数组。如果你想在数组中存储额外的unique_ptrin,没有理由不在初始化列表中使用make_unique
  • 是的,在这种情况下只涉及一个“新”。你提出的方法也不错。非常感谢!!!
【解决方案2】:

我认为@AchimGuetlein 提出的想法更好。

定义如下:

vector<unique_ptr<ClassA> > container;

for (i = 0; i<number of queues; ++i)
    container.emplace_back(make_unique<ClassA>(args to constructor of ClassA));

而不是:

unique_ptr<ClassA [] > ques = make_unique<ClassA [] >(n, ...);

虽然向量的元素可能会被移动,但我的队列没有发生移动。移动的objs只是unique_ptr self,但队列的地址永远不会改变。

很抱歉将其作为答案提交,因为代码示例无法在注释中优雅地显示为 codelet。

【讨论】:

  • 这样做,我不必担心是否会矢量移动元素。
  • 附带说明,您可以在此处使用push_back
猜你喜欢
  • 1970-01-01
  • 2011-05-17
  • 1970-01-01
  • 1970-01-01
  • 2017-01-07
  • 2020-12-26
  • 1970-01-01
  • 2018-05-11
  • 2013-08-10
相关资源
最近更新 更多