简体   繁体   English

C / C ++:“ Grid [x + y *宽度]”与“ Grid [x] [y]”

[英]C/C++: “Grid[x + y * width]” versus “Grid[x][y]”

This is extremely specific and has almost no ramifications, but it has always managed to bother me just because I didn't know which would be generally better. 这是非常具体的,几乎没有任何影响,但是它总是设法打扰我,只是因为我不知道哪种会更好。 I am hoping you fine folks will help me settle on one: 我希望你们中的好人能帮助我安顿下来:

Something ** grid; grid[x][y];
Something *  grid; grid[x + y * width];

I know anyone who has programmed has had to create a 2-dimensional array at some point. 我知道任何编程人员都必须在某个时候创建​​二维数组。 Which did you choose and what made you go that route? 您选择了哪一个,是什么让您走那条路的? Or perhaps you used another form altogether? 还是您完全使用了另一种形式?

Usually the second method is preferred, for a number of reasons: 通常出于多种原因,首选第二种方法:

  • A single multiplication is marginally faster than an extra array-dereference 单个乘法比额外的数组解引用快一点
  • Keeping the array contiguous also marginally increases speed, due to cache-hits 由于缓存命中,保持阵列连续也可以稍微提高速度
  • In many cases, such as loading a bitmap file, or working work DirectX/OpenGL surfaces, it is necessary to keep a 2D surface in one contiguous block of memory. 在许多情况下,例如加载位图文件或工作DirectX / OpenGL表面,必须将2D表面保留在一个连续的内存块中。
  • It only requires a single array allocation/deallocation 它只需要单个数组分配/取消分配
  • As a rule, it is easier to deal with pointers than pointers-to-pointers 通常,处理指针比使用指针指向指针要容易

As has been mentioned by several others, if you know the width at compile-time, declaring the variable as int grid[][width] will give you all the above advantages, with nicer syntax. 正如其他一些人提到的那样,如果您知道编译时的宽度,则将变量声明为int grid[][width]会以更好的语法为您提供上述所有优点。 Obviously if the width is dynamic, this is not an option. 显然,如果宽度是动态的,则这不是一个选择。

in first case you must create new pointer for each "x" in second case, you will immediately allocate memory my choice is 在第一种情况下,您必须为每个“ x”创建新的指针,在第二种情况下,您将立即分配内存,我的选择是

Something * grid; *网格 grid[x + y * width]; 格[x + y *宽度];

its less possibility of mistakes, eg access violation when you forgot to create subarray grid[x] with some x 错误的可能性较小,例如,当您忘记创建带有某些x的子数组grid [x]时发生访问冲突

In C, I would use typedef Something grid_t[][width]; grid[y][x] 在C语言中,我将使用typedef Something grid_t[][width]; grid[y][x] typedef Something grid_t[][width]; grid[y][x] (note the order and the explicit array size). typedef Something grid_t[][width]; grid[y][x] (注意顺序和显式数组的大小)。 I prefer not to use the jagged array Something **grid . 我不想使用锯齿状的数组Something **grid

In C++, I would use grid.get(x, y) , and inside the implemention would be either of them, so I can easily switch to a better representation when needed (eg triangular matrices). 在C ++中,我将使用grid.get(x, y) ,并且在实现内部将是它们中的任何一个,因此我可以在需要时轻松切换到更好的表示形式(例如,三角矩阵)。 Most likely I would start with a std::vector<Something>(height * width) to store the actual data. 我最有可能从std::vector<Something>(height * width)开始存储实际数据。

Do you access it linearly? 您是否线性访问它? The second would be better cache line use. 第二个是更好地使用缓存行。

But the first one is easier to read. 但是第一个更容易阅读。

Use the second form: 使用第二种形式:

  • LAPACK / CBLAS and most other external libraries requires the second form. LAPACK / CBLAS和大多数其他外部库需要第二种形式。
  • Representation is more compact [avoids additional vector of pointers, as in the first case] 表示更加紧凑[避免出现指针的向量,如第一种情况一样]
  • Representation is faster (grid[x][y] requires two pointer dereferences, not one) 表示速度更快(grid [x] [y]需要两个指针取消引用,而不是一个)
  • malloc is easier to handle [no need to do two-steps of malloc] malloc更易于处理[无需执行两步的malloc]

for contiguous access, the single-array version is more efficient. 对于连续访问,单阵列版本效率更高。 for random access, the single-array version still is more efficient [only requires one pointer dereference] 对于随机访问,单数组版本仍然更有效[仅需要取消引用一个指针]

In the first form the array doesn't have to be rectangular, that is each "line" can be a different size. 在第一种形式中,数组不必是矩形的,也就是说,每条“线”可以具有不同的大小。 I would generally prefer the second unless there is a concrete reason to treat each line seperately. 除非有具体理由分开对待每行,否则我通常会选择第二行。 It is more memory efficient, cacheable, faster. 它具有更高的内存效率,可缓存性,更快的速度。

A concrete example of the advantage is if you need to make a copy of the array. 优点的一个具体示例是是否需要复制阵列。 It is a single memcpy() using the second form but a lot more complicated with the first. 它是使用第二种形式的单个memcpy(),但与第一种形式相比要复杂得多。

For C++ there is also Boost.MultiArray 对于C ++,还有Boost.MultiArray

You could go either way with it, whatever you like (assuming you dont literally mean it is defined as something **grid, see ultor or Sjoerd's answers). 您可以随心所欲地使用它的任何一种方式(假设您从字面上并不意味着它被定义为** grid,请参见ultor或Sjoerd的答案)。 The first one is usually easier to type, the second one gives you more flexibility and control. 第一个通常更容易键入,第二个给您更多的灵活性和控制力。 Much of the time they will produce the same instructions, so to some extent it comes down to personal typing and coding habits, readability, maintainability, etc. 他们通常会产生相同的指令,因此在某种程度上取决于个人打字和编码习惯,可读性,可维护性等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM