初始化矢量<矢量的最快方法>大小为 0,容量<double>固定

Fastest way to initialize vector<vector<double>> with size 0 with fixed capacity

本文关键字:gt lt 固定 小为 double 容量 初始化 方法      更新时间:2023-10-16

什么是最快的方法:

template<typename T>
vector<vector<T>> vec_vec_init(T dummy_for_type, size_t outer_dim, size_t inner_dim) {
vector<vector<T>> v(outer_dim);
for (size_t i = 0; i < outer_dim; i++)
v[i].reserve(inner_dim);
return v;
}

即,如果我有

vector<vector<double>> v = vec_vec_init((double)0, 5, 10);

然后,大小为5的v矢量和每个v[i]是容量为10的空双矢量。

实际上不可能保证"最快",但我可能会这样做(假设C++11或更高版本)

template<typename T>
std::vector<std::vector<T> > vec_vec_init(std::size_t outer_dim, std::size_t inner_dim)
{
std::vector<std::vector<T> > v(std::vector<T>(0), outer_dim);
for (auto &i : v) i.reserve(inner_dim);
return v;
}

备注;

  • 我在名称空间std中添加了std::前缀,因为像这样的模板函数可能会在头文件中定义。有很多解释(在SO和其他地方,使用谷歌很容易找到)解释为什么using namespace std;在头文件中是个坏主意
  • 这使用迭代器,与标准容器上的数组索引相比,迭代器具有更好的性能(不能保证,但通常是公平的)。主观上,许多程序员(至少,一旦他们掌握了使用迭代器的窍门)也发现迭代器比数组索引更容易使用
  • 我已经删除了dummy_for_type参数,因为我认为像v = vec_vec_init<Something>(outer, inner)这样的调用比v = vec_vec_init(Something(0), outer, inner)或(如果Something不能初始化为0)vec_vec_init(dummy_Something, outer, inner)更清晰

在C++11之前,我不会麻烦使用这样的函数,因为它会按值返回。按值复制矢量可以保证保留大小(除非复制失败并引发异常),但不能保证保留容量。这也适用于这种情况下的内部向量。

所以我可能会完全取消这个功能,只需做这个

std::vector<std::vector<Something> > v(outer);
for (auto &i : v) i.reserve(inner);

或者(如果我要求代码在C++11之前工作)

std::vector<std::vector<Something> > v(outer);
std::vector<std::vector<Something> >::iterator i = v.begin(), end = v.end();
while (i != end)
{
i->reserve(inner);
++i;
}

您的解决方案几乎是最好的。您可以将其调整为:

template<typename T>
vector<vector<T>> vec_vec_init(T dummy, size_t outer_dim, size_t inner_dim) {
vector<vector<T>> v(outer_dim);
for (auto &inner: v)
inner.reserve(inner_dim);
return v;
}

感觉像:

vector<vector<T>> vec_vec_init(T dummy, size_t outer_dim, size_t inner_dim) {
vector<T> reserved;
reserved.reserve(inner_dim);    
vector<vector<T>> v(outer_dim, reserved);
return v;
}

应该工作(它用reservedouter_dim副本创建v)。问题是std::vector的复制构造函数(必然)保留容量。所以你所能保证的就是得到outer_dim的空向量。

顺便说一句,我会从调用序列中删除dummy_for_size,并作为调用

auto vv = vec_vec_init<float>( 100*1000, 10 );