如何在构造std :: vector时放置元素?

时间:2017-10-11 10:45:26

标签: c++11 vector constructor emplace

我想构造一个std::vector,其中包含一些元素,这些元素由某些特定构造函数而不是默认构造函数构造。换句话说,我想在构造向量时对元素进行处理。我怎么能这样做?

考虑this

struct Item
{
    Item(double) {}
    Item(const Item&) = delete;
    Item(Item&&) = delete;
};
std::vector<Item> vv(10, 3.14); // Fails! Tries to copy while I want to emplace.

2 个答案:

答案 0 :(得分:6)

您的Item课程不支持复制或移动。这样可以阻止std::vector上的大多数操作进行编译,包括std::vector::reservestd::vector::resize。如果你真的有这样的课程,你可能需要std::vector<std::aligned_storage_t<sizeof(Item), alignof(Item)>>代替。

如果可以向Item添加移动构造函数,则可以创建辅助函数(因为您正在使用的构造函数重载是根据复制定义的)。请注意,以下版本仅适用于一元构造函数。

template <typename T, typename Arg>
auto make_vector(std::size_t n, Arg&& arg)
{
    std::vector<T> result;
    result.reserve(n);

    for(std::size_t i = 0; i < n; ++i)
        result.emplace_back(arg);

    return result;
}

用法:

auto vec = make_vector<Item>(10, 3.14);

答案 1 :(得分:3)

您可以使用带有两个迭代器的向量构造函数。例如,您可以使用vector<double>

中的迭代器
std::vector<double> init(10, 3.14);
std::vector<Item> vv(init.begin(), init.end());

Live demo

或者您可以编写自己的自定义迭代器类来进行初始化:

struct ItemInitializer {
  int index;
  double value;

  using value_type = double;
  using difference_type = int;  
  using pointer = const double*;
  using reference = const double&;
  using iterator_category = std::forward_iterator_tag;

  ItemInitializer() : index(0), value(0.0) {}
  ItemInitializer(int index, double v = 0.0) : index(index), value(v) {}

  bool             operator!=(const ItemInitializer& other) const { return other.index != index; }
  ItemInitializer& operator++() { index++; return *this; }
  ItemInitializer  operator++(int) { ItemInitializer ret(index, value); index++; return ret; }
  const double&    operator*() const { return value; }  
  const double*    operator->() const { return &value; } 
};

std::vector<Item> vv(ItemInitializer{0, 3.14}, ItemInitializer{10});

Live demo