STL矢量矢量 - 好主意?调整“内部”向量的机制?

时间:2013-03-13 10:54:27

标签: c++ data-structures vector stl

我经常需要将整数0...N-1中的映射表示为某种类型T的列表。对于单个列表,我需要动态添加元素到最后。 N通常是预先知道的(但不是在编译时)。我需要快速访问各个列表。

我通常使用vector<vector<T> > my_map(N)实现此功能,并使用my_map[key].push_back(val)添加元素。

我有两个问题:

这是实现这种地图的有效推荐方式吗?

另外,我想知道元素的连续性及其对调整大小的影响。说,我添加了一个my_map[key].push_back(val)的元素,而my_map[key]需要key != N-1来调整大小。这会触发整个向量my_map的副本以保持其内容连续吗?或者是my_map在内部实现了指向堆上向量的指针?

我知道这可能取决于STL的实现。我主要对Visual Studio 2010的机制(和速度影响)和Linux中的GCC感兴趣。


更新

在评论中,@ PeterWood指出我将std::deque作为列表的容器,不需要重新分配来增长。我做了一些不科学的基准测试,将vector< deque<T> >vector< vector<T> >unsigned int作为T进行比较。对于两者,我定时了100万个包含30个元素的列表,以及10,000个列表,每个包含3000个元素。请注意,我的测试反映了我对此类数据结构的典型应用场景。

我定时随机访问“build-up”,其工作原理如下:

vector<ContainerT> my_map(numKeys);
vector<unsigned int> random_keys(numKeys);
for (unsigned int i=0; i<numKeys; ++i) random_keys[i] = i;
random_shuffle(random_keys.begin(),random_keys.end());

for (auto pKey=random_keys.begin(); pKey!=random_keys.end(); ++pKey)
{
  for (unsigned int i=0; i<listSize; ++i)
  {
    my_map[*pKey].push_back( rand() );
  }
}

我定时从随机选择的列表中查询3000万个随机元素。

结果

对于许多小型列表,

deque的构建速度稍快,但查询的方式比两种方案的向量都慢。我的结论是,由于我的问题,我与vector< vector<T> >保持联系。

deque

Keys: 1000000, list size: 30
Mean time buildup: 1.29517 seconds
Mean time query: 4.17624 seconds

Keys: 10000, list size: 3000
Mean time buildup: 0.998761 seconds
Mean time query: 5.052 seconds


vector

Keys: 1000000, list size: 30
Mean time buildup: 1.5347 seconds
Mean time query: 1.63043 seconds

Keys: 10000, list size: 3000
Mean time buildup: 0.604954 seconds
Mean time query: 1.58328 seconds

3 个答案:

答案 0 :(得分:2)

  

这是实现这种地图的有效推荐方式吗?

我认为这是实现这种地图的完美合理方式。

  

另外,我想知道元素的连续性及其对调整大小的影响。说,我添加了一个my_map[key].push_back(val)的元素,而my_map[key]需要key != N-1来调整大小。这会触发整个向量my_map的副本以保持其内容连续吗?或者是my_map在内部实现了指向堆上向量的指针?

不,它不会触发整个外部矢量的副本。只有子矢量是连续的;整个矢量一般不是。

就心理模型而言,您可以将my_map视为指向1D数组的指针数组,而不是单个连续的2D数组。

答案 1 :(得分:0)

它复制外部矢量中的矢量对象。但是这些向量内的堆上的对象不会被重新分配。

答案 2 :(得分:0)

每个std :: vector通常都有一个指向内存的内部指针,它指向T类型的对象数组。

在这种类型为T的向量向量中,调整内部向量的大小不会调整外部向量的大小(在您的示例中为my_map),因为外部向量只能被视为指向此类数组的指针向量。内部矢量数组位于除外部矢量之外的其他存储器位置。

出于同样的原因,my_map

的内部向量之间没有连续性