Ste*_*ein 11 c++ stl vector c++11
我有以下类型:
std::vector<std::vector<int>> indicies
Run Code Online (Sandbox Code Playgroud)
其中内部向量的大小始终为2.问题是,向量在内存中是非连续的.我想用连续的东西替换内部向量,以便我可以抛出扁平数组:
int *array_a = (int *) &(a[0][0])
Run Code Online (Sandbox Code Playgroud)
如果新类型有[]运算符会很好,所以我不必更改整个代码.(如果有必要,我也可以自己实施).我的想法是:
std::vector<std::array<int, 2>>
Run Code Online (Sandbox Code Playgroud)
要么
std::vector<std::pair<int, int>>
Run Code Online (Sandbox Code Playgroud)
这些在内存中看起来如何?我写了一个小测试:
#include <iostream>
#include <array>
#include <vector>
int main(int argc, char *argv[])
{
using namespace std;
vector<array<int, 2>> a(100);
cout << sizeof(array<int, 2>) << endl;
for(auto i = 0; i < 10; i++){
for(auto j = 0; j < 2; j++){
cout << "a[" << i << "][" << j << "] "
<<&(a[i][j]) << endl;
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这导致:
8
a[0][0] 0x1b72c20
a[0][1] 0x1b72c24
a[1][0] 0x1b72c28
a[1][1] 0x1b72c2c
a[2][0] 0x1b72c30
a[2][1] 0x1b72c34
a[3][0] 0x1b72c38
a[3][1] 0x1b72c3c
a[4][0] 0x1b72c40
a[4][1] 0x1b72c44
a[5][0] 0x1b72c48
a[5][1] 0x1b72c4c
a[6][0] 0x1b72c50
a[6][1] 0x1b72c54
a[7][0] 0x1b72c58
a[7][1] 0x1b72c5c
a[8][0] 0x1b72c60
a[8][1] 0x1b72c64
a[9][0] 0x1b72c68
a[9][1] 0x1b72c6c
Run Code Online (Sandbox Code Playgroud)
它似乎适用于这种情况.这种行为是标准还是巧合?有一个更好的方法吗?
Anarray<int,2>
将是一个包含数组的结构体int[2]
;该标准没有直接强制要求它,但确实没有其他明智且实用的方法来做到这一点。
请参阅标准中的 23.3.7 [数组]。我发现标准中没有任何内容要求sizeof(std::array<char, 10>)==1024
是错误的。这将是一个荒谬的 QOI(实施质量);我见过的每个实现都有sizeof(std::array<T,N>) == N*sizeof(T)
,以及其他我认为有敌意的东西。
数组必须是连续的容器,它们是可以由最多可转换N
为 的类型的参数初始化的聚合T
。
标准允许在此类数组之后进行填充。我知道有 0 个编译器插入了这样的填充。
不保证连续的缓冲区std::array<int,2>
能够作为 的平面缓冲区被安全地访问int
。事实上,别名规则几乎肯定会禁止诸如未定义行为之类的访问。你甚至不能用int[3][7]
! 请参阅此问题和解答,以及此处和此处。
大多数编译器都会使您所描述的工作正常,但优化器可能会决定通过 anint*
和通过 the 的访问array<int,2>*
无法访问相同的内存,并生成疯狂的结果。看来不值得。
符合标准的方法是编写一个数组视图类型(它采用两个指针并形成一个可[]
重载的可迭代范围)。然后编写平面缓冲区的二维视图,其中较低维度是运行时或编译时值。[]
然后它会返回一个数组视图。
和其他“标准扩展”库中将会有代码boost
为您执行此操作。
将 2d 视图与拥有向量的类型合并,即可得到 2d 向量。
唯一的行为差异是,当矢量代码的旧矢量复制较低维度(如auto inner=outer[i]
)时,它会复制数据,然后它将创建一个视图。
归档时间: |
|
查看次数: |
882 次 |
最近记录: |