我有一个定义的类 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/