二维std :: array上的初始化列表

时间:2014-02-21 19:56:02

标签: c++ c++11

为什么int的二维数组是连续初始化的?同时,每组数字初始化二维向量。

int main()
{
  array<array<int, 2>, 2> td{ 2, 6, 4, 8 }; //array of arrays
  for (int i = 0; i < 2; ++i)
    for(int j = 0; j < 2; ++j)
      cout << td[i][j] << ' ';

  cout << endl;

  vector<vector<int>> vtd{ { 5, 1 }, { 0, 2 } };  //vector of vectors
  for (int i = 0; i < 2; ++i)
    for (int j = 0; j < 2; ++j)
      cout << vtd[i][j] << ' ';

  return 0;
}

结果如下:

2 6 4 8
5 1 0 2

4 个答案:

答案 0 :(得分:3)

std::array是一个聚合。当使用像这样的braced-init-list初始化聚合时,每个子聚合按顺序从列表中获取所需数量的元素,列表的其余部分用于初始化下一个元素,依此类推。特别是,这意味着td中的第一个数组占用前两个初始化器(因为它有两个元素),第二个数组占用剩下的两个元素。

std::vector不是聚合,并且有一个显式定义的构造函数,它将std::initializer_list作为参数,它决定了列表初始化的语义。

答案 1 :(得分:1)

数组数组和向量向量之间的差异与正常数组数组相对于指向指针的指针相同。

std::array类非常接近普通数组(必须是连续的),而std::vector则关闭指针。

答案 2 :(得分:1)

std::vector是一个封装一组内部状态的对象:{ T* data, size_t count, size_t capacity }。向量的实际内容存储在其他地方的内存中。

相比之下,std::array是C风格数组周围的封装层。它没有内部状态,但直接位于C阵列上。

std::vector<int> v;
v.reserve(4);
std::array<int, 4> a;

在此之后,你在堆栈上的内容如下:

[ int* v.data ]
[ size_t v.count = 0 ]
[ size_t v.size = 4 ]
[ int[4] ]

因此,您的2层std::vector实际上是对象的向量,

[ std::vector<int>* v.data --> points to second tier object in heap memory ]
[ size_t v.count ]
[ size_t v.size ]

std::array实际上只是int a[2][2]的封面,它会按照您期望的方式进行初始化。

答案 3 :(得分:0)

std::array是一个非常薄的静态数组包装器。它在编译时分配,具有已知大小,并且每个元素都保证是连续的,因此当你有一个数组数组时,它们都将是连续的。

示例:

std::array<T, 4> a;
|   a[0]   |   a[1]   |   a[2]   |   a[3]   |

std::array<std::array<T, 2>, 2> b;
|   a[0][0]   |   a[0][1]   |   a[1][0]   |   a[1][1]   |

由于第一个数组(a[0])保证是连续的(就像第二个数组一样),并且父包装器数组也保证是连续的,整个结构将是连续的。

对于矢量,它在运行时确定。保证向量的动态数组是连续的,如果它是向量的向量,则父向量中的每个元素都有一个指向单独的连续内存块的指针(每个“子”向量具有大小,容量和指针)到一块连续的记忆中。)

类比如下:

T t[...][...] ====> std::array<std::array<T, ...>, ...>
T** t         ====> std::vector<std::vector<T>>