c++ - 在 C++ 中向 std::vector 添加任意数量的元素的最有效方法是什么?

标签 c++ c++11 vector variadic-functions

我有一个定义的类 A 和一个 std::vector vec 存储一系列 A实例。我尝试编写一个函数,将任意数量的 A 实例附加到 vec

我是否应该将 vec.reserve()vec.push_back() 一起使用,因为不断调整 vector 的大小很昂贵?或者,我应该使用 vec.insert() 吗?

目前,我不确定我是否应该将函数设计为接受可变数量的参数,使用可变函数或我想组合然后连接的 A 实例的 vector vec?

设计这个函数的有效方法是什么(速度很关键,A 是一个复杂的类)?

最佳答案

我认为以下应该涵盖常见情况。 rref_capture 技巧来自 this answer .这一切的重点是尽可能移动值。

您还可以使用另一个答案中给出的可变参数模板版本。

// https://github.com/KubaO/stackoverflown/tree/master/questions/vector-append-40274282
#include <array>
#include <cassert>
#include <initializer_list>
#include <iterator>
#include <type_traits>
#include <vector>

template<typename T>
class rref_capture {
   T* ptr;
public:
   rref_capture(T&& x) : ptr(&x) {}
   operator T&& () const { return std::move(*ptr); } // restitute rvalue ref
};

template <typename T>
void append(std::vector<T> & v,
            typename std::decay<std::initializer_list<rref_capture<T>>>::type u) {
   v.reserve(v.size() + u.size());
   for (auto && item : u)
      v.push_back(std::move(item));
}

template <typename T, typename U>
void append(std::vector<T> & v, U && u) {
   v.reserve(v.size() + std::distance(std::begin(u), std::end(u)));
   for (auto & item : u)
      v.push_back(std::move(item));
}

template <typename T, typename U>
void append(std::vector<T> & v, U & u) {
   v.reserve(v.size() + std::distance(std::begin(u), std::end(u)));
   for (auto & item : u)
      v.push_back(item);
}

struct A {
   static int copies, moves;
   A() {}
   A(A&&) { moves++; }
   A(const A&) { copies++; }
   A& operator=(const A&) { copies++; return *this; }
   static void reset() { A::copies = 0; A::moves = 0; }
};
int A::copies, A::moves;

int main() {
   std::vector<A> vec;
   vec.reserve(100);

   A::reset();
   append(vec, {A(), A()});
   assert(A::copies == 0 && A::moves == 2 && vec.size() == 2);

   auto vec2 = vec;
   A::reset();
   append(vec, vec2);
   assert(A::copies == 2 && A::moves == 0 && vec.size() == 4);

   A::reset();
   append(vec, std::move(vec2));
   assert(A::copies == 0 && A::moves == 2 && vec.size() == 6);

   A::reset();
   append(vec, std::array<A,2>{A(), A()});
   assert(A::copies == 0 && A::moves == 2 && vec.size() == 8);

   const std::vector<A> cvec{2};
   A::reset();
   append(vec, cvec);
   assert(A::copies == 2 && A::moves == 0 && vec.size() == 10);

   A arr[2];
   A::reset();
   append(vec, arr);
   assert(A::copies == 2 && A::moves == 0 && vec.size() == 12);
}

关于c++ - 在 C++ 中向 std::vector 添加任意数量的元素的最有效方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40274282/

相关文章:

c++ - 返回一个 unique_ptr<T> 。概念澄清

c++ - 将较小长度的 vector 返回到已填充的 vector

c++ - 两个类的 "Addition"

c++ - 如何使用QT插入到SQL数据库表中

c++ - 我写了这个方法来删除链表的重复元素,但它显示段错误,为什么?

c++ - 您可以防止在编译时通过父级调用继承的私有(private)成员吗?

c++ - 如何允许最终用户使用正则表达式创建验证规则?

c - Realloc:结构动态 vector 中的下一个大小无效

c++ - STL deque pop_front() 会自动回收内存吗?

c++ - 存放高分表,用什么容器?