我有一个这样的列表列表:
std::list<std::list<double> > list;
我在其中填充了一些带有双精度的列表(实际上很多,这就是我不使用向量的原因。所有这些复制都占用了很多时间。)
假设我想访问可以访问的元素,就像list[3][3]
列表不是列表而是向量或二维数组一样。我该怎么做?
我知道访问列表中的元素是通过使用迭代器来完成的。我不知道如何摆脱双重。
我有一个这样的列表列表:
std::list<std::list<double> > list;
我在其中填充了一些带有双精度的列表(实际上很多,这就是我不使用向量的原因。所有这些复制都占用了很多时间。)
假设我想访问可以访问的元素,就像list[3][3]
列表不是列表而是向量或二维数组一样。我该怎么做?
我知道访问列表中的元素是通过使用迭代器来完成的。我不知道如何摆脱双重。
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;
}
要严格回答您的问题,Joachim Pileborg 的回答是要走的路:
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>
会更好。Avector<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
内部列表中的每个,它必须分配至少两个额外的指针,并且还必须为全局最少内的每个列表分配两个额外的指针。这意味着你的容器占用的总内存大约是向量的三倍。而所有这些分配和管理也需要额外的运行时间。
要真正回答您的问题,您可能应该查看std::advance
.