插入到仅移动类型的向量中

时间:2019-02-17 08:28:37

标签: c++ vector stl c++17

我有一个std::vector<std::unique_ptr<T>>。我想insert一些nullptr进入此向量的中间。我尝试了vec.insert(first, size, nullptr),但这显然不起作用,因为需要复制nullptr。我可以反复使用insert的单数形式,但我想知道是否有更有效的方法。

2 个答案:

答案 0 :(得分:6)

“有效”是要衡量的。但是,如果您想一口气移动元素,而不是不断将元素向右移动,可以使用std::rotate。这是

vec.resize(vec.size() + size); // Add the "null" pointers to the end.
// Obtain valid first after resize
std::rotate(first, vec.end() - size, vec.end());

由于rotate的功能是使中间迭代器成为范围的“新优先”,而其前面的迭代器则是“新末”,因此上述选择的迭代器将移动null的范围指向其预期位置的指针(在第一个之前)。

此外,由于标记了C ++ 17,因此您还可以将标准算法传递给执行策略,并希望获得一些并行性来启动。

答案 1 :(得分:0)

您可以放在一起自己的迭代器,该迭代器在被取消引用后将创建默认实例。这些是prvalue,可在向量中构造仅移动类型。使用计数此类迭代器的实例来调用std::vector::insert。这是一个可能不符合标准但可以正常工作的示例。

template <class T>
class DefaultCtorInputIt {
   public:
      DefaultCtorInputIt(size_t n) : n(n) {}

      using value_type = T;
      using reference = T;
      using pointer = T;
      using iterator_category = std::input_iterator_tag ;
      using difference_type = int;
      using Self = DefaultCtorInputIt; // save typing (below)

      value_type operator *() { return T(); }
      Self& operator ++() { ++n; return *this; }

      friend bool operator == (const Self& lhs, const Self& rhs) {
         return lhs.n == rhs.n;
      }

      friend bool operator != (const Self& lhs, const Self& rhs) {
         return !(lhs == rhs);
      }

   private:
      size_t n;
};

这样,您可以

std::vector<std::unique_ptr<int>> v;

 // Fill v with some values...

using NullUPtr =DefaultCtorInputIt<std::unique_ptr<int>>; // save typing

// Insert 10 default constructed instances at desired position:
v.insert(v.begin() + 42, NullUPtr(0), NullUPtr(10));

请注意,要使其尽可能高效,您可能应该确保上述迭代器符合随机访问迭代器的要求,以便可以预先使用O(1)计算范围[NullUPtr(0), NullUPtr(10))的大小。只分配一次内存。手工制作自己的迭代器类型时,还值得一看Boost iterator facade