我已经围绕长寿命向量的共同主题编写了无数的软件模块,有时(在未指定的频率下)必须更新其内容.
惯用法实施:
void LongLived::reconfigure(const InputT& whatever_input)
{
m_vector.clear();
m_vector.reserve(whatever_input.size());
populate(m_vector, whatever_input);
}
Run Code Online (Sandbox Code Playgroud)
请注意,惯用实现永远不会减少其内部缓冲区的容量.如果这不好怎么办?只是用shrink_to_fit()
,我想:
void LongLived::reconfigure(const InputT& whatever_input)
{
m_vector.clear();
m_vector.reserve(whatever_input.size());
m_vector.shrink_to_fit(whatever_input.size()); // ? Here
populate(m_vector, whatever_input);
}
Run Code Online (Sandbox Code Playgroud)
哦,那将是多么美好......但令我惊讶的是,它没有编译,因为shrink_to_fit()
不需要一个数字!
shrink_to_fit()
应该使用的方式显然是先填充向量.然后,你调用shrink_to_fit()
,这将从事后的向量中的元素数量中获得容量需求,但如果我事先已经告诉它,那显然是次优的,因为现在,所有内容都必须被移动.
目标:我想vector_reserve_or_shrink()
在这种情况下使用一个函数:
void LongLived::reconfigure(const InputT& whatever_input)
{
m_vector.clear();
vector_reserve_or_shrink(m_vector, whatever_input.size()); // ? Implement this!
populate(m_vector, whatever_input);
}
Run Code Online (Sandbox Code Playgroud)
我实际上并不痴迷于从矢量中删除每个未使用的字节.更确切地说,我很乐意将其留给某些实现定义,例如shrink_to_fit()
,可能知道分配器的怪癖,并可能选择什么都不做.通过这种方式,人们不会冒险进行抽象反转,从而否定任何较低级别的优化.例如,假设分配器的粒度是16:那么,当你要求一个时,矢量实现可能会免费给你15个字节,据我所知,这对于尝试回馈只会适得其反.
使用这样的东西:
template <typename VECTOR>
void setCapacity(VECTOR &vector, std::size_t capacity) {
if (capacity < vector.size()) capacity = vector.size();
if (vector.capacity() > capacity) {
VECTOR v;
v.reserve(capacity);
std::size_t size = vector.size();
for (std::size_t i = 0; i < size; i++) {
v.emplace_back(std::move(vector[i]));
}
vector.swap(v);
} else {
vector.reserve(capacity);
}
}
Run Code Online (Sandbox Code Playgroud)
它将向量容量设置为capacity
(如果可能),同时保留元素。而且它只进行一次分配。
归档时间: |
|
查看次数: |
487 次 |
最近记录: |