传染媒介,储备

OSE*_*OSE 23 c++ stdvector

假设我想表示int作为向量向量的二维矩阵:

std::vector<std::vector<int> > myVec;
Run Code Online (Sandbox Code Playgroud)

内部尺寸是常数,比如5,外部尺寸小于或等于N.为了尽量减少重新分配,我想保留空间:

myVec.reserve(N);
Run Code Online (Sandbox Code Playgroud)

内部向量的大小是多少?这纯粹依赖于实现吗?这如何影响数据的空间局部性?由于内部维度是常量,有没有办法告诉编译器使用这个常量大小?如果内部向量的大小发生变化,这些答案如何变化?

Ben*_*igt 14

由于你的内在维度不变,我认为你想要

std::vector< std::array<int, 5> > vecs;
vecs.reserve(N);
Run Code Online (Sandbox Code Playgroud)

这将为您提供预分配的连续存储,这是性能的最佳选择.

  • 这只适用于C++ 11,请提及它. (2认同)
  • @Samer:那是胡说八道,“ array”不需要任何C ++ 11功能,自2007年起就可以作为“ std :: tr1 :: array”使用,甚至可以在以前作为“ boost :: array”使用。 (2认同)

us2*_*012 8

内部向量的大小与调整外部向量的大小完全无关.对于您的向量包没有局部性保证,仅对于单个向量存在局部性保证(即,内存中的连续块).

请记住,矢量对象本身具有常量sizeof-size,其实际数据通常是动态分配的.对于第一近似,外向量是与内向量的N'指针的连续块.您的reserve调用不会为内部向量的可能元素保留内存,但仅针对内部向量对象本身(即其簿记数据及其指向动态分配的数据块的指针).


The*_*ist 5

内部向量使用默认构造函数初始化。因此,如果您写:

vector<vector<int> > vecs;
vecs.reserve(10);
Run Code Online (Sandbox Code Playgroud)

这等同于调用的constuctor vector<int>vector<int>()为每个元件。这意味着您将拥有零尺寸的向量。但是请记住,除非调整向量大小(不保留),否则不能使用它们。

还要记住,有时使用所需的初始大小进行调整可能更有效。所以做类似的事情很有用

vector<vector<int> > vecs(3,vector<int>(5));
Run Code Online (Sandbox Code Playgroud)

这将创建一个大小为3的向量,并且每个元素将包含一个大小为5的向量。

还要记住,如果要经常调整向量的大小,则使用双端队列而不是向量可能更有效。它们很容易使用(作为向量),并且您不需要保留,因为元素在内存中并不连续。

  • `reserve()` 不会调用默认构造函数!因此不初始化。它只分配内存。 (2认同)
  • @ZoomIn“直观”是主观的。我对这种形式很满意,因为我了解 `std::vector` 的构造函数是如何工作的。您正在构建一个由 3 个元素组成的向量,每个元素都以 `vector&lt;int&gt;(5)` 作为初始值。对我来说这是有道理的。如果我们接受你的做法,那就意味着用整数初始化向量是可以的,这会导致各种问题并引入类型安全问题。想象一下接受 `std::vector&lt;int&gt; v = 5`...这意味着什么?!一切都令人困惑。 (2认同)