我有这个:
size_t n = 100;
std::vector<std::vector<foo>> v(n);
sub vectors
的计数是动态的,但已知。但是,每个vector
中的项目数量尚不清楚,但我对其进行了估算,因此我希望reserve
sub vectors
之后再开始推回它们。我目前正在做的是:
size_t estimated_size = 1000;
for (auto& sub_vector: v){
sub_vector.reserve(estimated_size);
}
有更好的方法吗?喜欢在构建时这样做吗?
P.S。这不是一个选择:
size_t n = 100;
size_t estimated_size = 1000;
std::vector<std::vector<foo>> v(n, std::vector<foo>(estimated_size));
我只想保留而不构造,因为foo
是构建两次的costy。
答案 0 :(得分:3)
如果确实希望在构造vector
时执行此操作,则可以使用带有两个迭代器的constructor并提供自己的自定义迭代器。取消引用迭代器会创建一个向量保留它然后返回它:
class VectorReserveItr : public std::iterator<std::input_iterator_tag, foo> {
size_t i;
size_t capacity;
public:
VectorReserveItr(size_t i, size_t capacity) : i(i), capacity(capacity) {}
VectorReserveItr& operator++() { ++i; return *this; }
bool operator!=(const VectorReserveItr& rhs) { return i != rhs.i; }
std::vector<foo> operator*() {
std::vector<foo> ret;
ret.reserve(capacity);
return ret;
}
};
std::vector<std::vector<foo>> v(VectorReserveItr(0, 1000), VectorReserveItr(100, 1000));
但我不希望它比循环更快,我认为它也不会更易读。
答案 1 :(得分:2)
这是一个快速倒计时迭代器:
template<class F,
class T=std::result_of_t<F const&(std::size_t const&)>
>
struct countdown_iterator:
std::iterator<
std::input_iterator_tag,
T,
std::ptrdiff_t,
T*,
T
>
{
using self=countdown_iterator;
std::size_t count_down = 0;
F f;
T operator*() const {
return f(count_down);
}
self& operator++() {
--count_down;
return *this;
}
self operator++(int) {
auto result = *this;
++(*this);
return result;
}
friend bool operator==(self const& lhs, self const& rhs) {
return lhs.count_down == rhs.count_down;
}
friend bool operator!=(self const& lhs, self const& rhs) {
return !(lhs==rhs);
}
};
半个范围的课程:
template<class It>
struct range {
It b, e;
It begin() const { return b; }
It end() const { return e; }
bool empty() const { return begin()==end(); }
decltype(auto) front() const { return *begin(); }
range():b(),e() {}
range(It s, It f):b(s), e(f) {}
range(range const&)=default;
range& operator=(range const&)=default;
~range() = default;
template<class C,
class=std::enable_if_t<!std::is_same<std::decay_t<C>, range>>
>
range( C&& c ):
range(std::begin(std::forward<C>(c)), std::end(std::forward<C>(c)))
{}
};
template<class It>
range<It> make_range( It b, It e ) { return {std::move(b),std::move(e)}; };
然后我们可以数:
template<class F,
class dF=std::decay_t<F>,
class It=countdown_iterator<dF>
class R=range<It>
>
R countdown( std::size_t N, F&& f ) {
countdown_iterator e( N, f ):
countdown_iterator b( N, std::forward<F>(f) );
return {std::move(b),std::move(e)};
}
使用:
size_t n = 100;
size_t m = 1000;
auto src = countdown(
n,
[m](auto&&){ std::vector<foo> v; v.reserve(m); return v; }
);
std::vector<std::vector<foo>> v;
v.reserve(100);
v.insert(v.end(), src.begin(), src.end() );
这里我们创建一个倒计时&#34;输入&#34;运行100个迭代器的迭代器。每次取消引用它时,它都会返回一个容量为m
的向量。
答案 2 :(得分:1)