如何在原位创建+填充容器?

时间:2019-01-11 14:25:39

标签: c++ in-place

我正在尝试创建无法复制或移动的类的数组。因此,我需要就地创建对象,但我不知道该怎么做:

#include <vector>

struct Foo {
  Foo(int) { }
  Foo(const Foo &) = delete;
  Foo & operator =(const Foo &) = delete;
  Foo(Foo &&) = delete;
  Foo & operator =(Foo &&) = delete;
};

struct Bla {
  Bla(const std::vector<int> & args) {
    for (auto i : args) {
      foo.emplace_back(i);
    }
  }
  std::vector<Foo> foo;
};

编译器抱怨删除的move构造函数,因为不能保证所有对象都是就地构造并且永远不会移动。我不必使用std::vector作为容器,因此可以随意提出其他建议。

3 个答案:

答案 0 :(得分:5)

您可以使用std::vector的迭代器对构造函数构造类似的对象

Bla(const std::vector<int> & args) 
    : foo(args.begin(), args.end())
{}

如果您需要在构造中包含其他参数,则可以切换到任何基于节点的容器,例如std::list

struct Bla {
  Bla(const std::vector<int> & args) {
    for (auto i : args) {
      foo.emplace_back(i, some_other_argument);
    }
  }
  std::list<Foo> foo;
};

答案 1 :(得分:2)

一种方法是使用范围构造函数。通过随机访问迭代器时,它不会重新分配向量:

Bla(const std::vector<int> & args) 
    : foo(args.begin(), args.end())
{}

答案 2 :(得分:1)

  

对于最一般的情况,是否没有某种方法可以通过向量args和lambda来创建初始化列表?

创建无法复制或移动的Foo的STL容器的另一种方法是包含std::unique_ptr<Foo>,该容器是可移动的。 例如,作为更一般的情况,如果Foo的ctor的第一个和第二个参数分别是intdouble,那么下面的Bla将为您工作: / p>

DEMO

#include <tuple>
#include <vector>
#include <memory>

struct Bla
{
    Bla(const std::vector<std::tuple<int, double>>& args)
    {
        foo.reserve(args.size());

        for (const auto& i : args) {
            foo.push_back(
                std::make_unique<Foo>(std::get<0>(i), std::get<1>(i)));
        }
    }

    std::vector<std::unique_ptr<Foo>> foo;
};