用平坦的记忆结构替换矢量矢量

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)

它似乎适用于这种情况.这种行为是标准还是巧合?有一个更好的方法吗?

Yak*_*ont 2

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 次

最近记录:

8 年,8 月 前