我有一个像这样的列表列表:
std::list<std::list<double> > list;
我在其中填写了一些带有双打的列表(实际上非常多,这就是为什么我没有使用向量。所有这些复制都需要花费很多时间。)
如果列表不是列表而是矢量或二维数组,我想要访问可以像list[3][3]
那样加入的元素。我该怎么做?
我知道访问列表中的元素是通过使用迭代器完成的。我无法弄清楚如何摆脱双重。
答案 0 :(得分:4)
double item = *std::next(std::begin(*std::next(std::begin(list), 3)), 3);
使用矢量通常会有更好的表现;访问列表的元素n
是O(n)。
如果您担心拼接容器内部的性能,可以使用deque
,operator[]
,从任一端分摊常量插入和删除,以及线性时间插入和删除来自内部。
对于C ++ 03编译器,您可以自己实现begin
和next
:
template<typename Container>
typename Container::iterator begin(Container &container)
{
return container.begin();
}
template<typename Container>
typename Container::const_iterator begin(const Container &container)
{
return container.begin();
}
template<typename T, int n>
T *begin(T (&array)[n])
{
return &array[0];
}
template<typename Iterator>
Iterator next(Iterator it, typename std::iterator_traits<Iterator>::difference_type n = 1)
{
std::advance(it, n);
return it;
}
答案 1 :(得分:1)
要真正回答您的问题,您应该查看std::advance
。
答案 2 :(得分:1)
要严格回答您的问题,Joachim Pileborg's回答是要走的路:
std::list<std::list<double> >::iterator it = list.begin();
std::advance(it, 3);
std::list<double>::iterator it2 = (*it).begin();
std::advance(it2, 3);
double d = *it2;
现在,根据您的问题和进一步的评论,您是否总是在列表的末尾添加元素或者可以在任何地方添加元素并不清楚。如果您总是添加到最后,vector<double>
将会更好。每次大小增加时都不需要复制vector<T>
;只有当容量增加时,这是一个非常不同的事情。
除此之外,正如其他人之前所说的,使用reserve()
将对重新分配有很大帮助。您不需要为所有向量的组合大小保留,但仅针对每个单独的向量。所以:
std::vector<std::vector<double> > v;
v.reserve(512); // If you are inserting 400 vectors, with a little extra just in case
您还可以为vector<double>
内的每个v
预留。就是这样。
考虑到您的列表清单会占用更多空间。对于内部列表中的每个double
,它必须至少分配两个额外的指针,并且还要为全局最小值内的每个列表分配两个额外的指针。这意味着容器占用的总内存大约是向量的三倍。所有这些分配和管理也需要额外的运行时间。