C++ 多维数组成员访问器
C++ multidimensional array member accessor
我有一个 class,里面有一个大的二维数组。它曾经是一个分配在堆上的动态数组,现在它是我更喜欢的静态大小。
private:
int fontTextureCoords_[100][7];
我必须将类型转换添加到访问器,以便 return 数组在 class 之外访问,目前工作正常,但我不确定它是否安全或者正确的处理方式。
public:
inline int **getFontTextureCoords()
{
return (int**)fontTextureCoords_;
}
这样做安全/正确吗?还是有更好的方法 return指向多维数组的指针?
将 int fontTextureCoords_[100][7];
之类的数组转换为 int**
是不正确的。它会导致未定义的行为。
如果不是太多,把getFontTextureCoords
改成:
inline int (*getFontTextureCoords()) [7]
{
return fontTextureCoords_;
}
并将其用作:
int (*ptr)[7] = getFontTextureCoords();
如果您可以选择使用std::vector
或std::array
,最好使用它们。
这不是正确的方法,不应编译。二维数组不能转换为指向指针的指针。您必须 return 一个指向数组的指针,使用 typedef 最容易编写:
using T = int[7];
inline T* getFontTextureCoords() { return fontTextureCoords_; }
尽管仅 return 引用整个数组会好得多:
using T = int[100][7];
inline T& getFontTextureCoords() { return fontTextureCoords_; }
你也可以 std::array<std::array<int, 7>, 100>
。
C/C++中没有多维数组。只有一维数组。你可以有一个一维数组,它的每个元素都是另一个一维数组。虽然看起来没有什么区别,但它是存在的,而且非常重要。
这正是传递逻辑不起作用的方式。每个人都经历过。 'If single-dimensional arrays are passed as a pointer to the first elelement, 2-D arrays should be passed as a pointer to pointer to first element, etc'。但由于它不是二维数组,而是数组的数组,所以无法应用该逻辑。
您可以通过以下方式进行推理。比方说,你有一个类型为 X 的数组。
X x[10];
如何访问第 5 个元素?简单 -
x[5] = 42;
但是编译器在看到它时会做什么?它大致是这样的:
*(&x[0] + 5) = 42;
所以它获取第一个元素的地址,并将其加 5 以获得第 5 个元素的地址。但是加 5 意味着什么呢?以字节为单位,应从数组开头的地址跳过多少字节才能到达请求的内存位置?当然是 5 * sizeof(X)。现在,如果你有“二维”数组,声明如下:
X x[2][3];
并且您尝试通过指向指针的指针来使用它:
px = (X**)x;
px[3][4] = 42;
记住,为了生成[][]的代码,编译器需要用*(px + )的方式表达。并且必须是数组的大小(因为数组的元素是数组)。但是为此您需要知道数组大小,正如您所见,您的 px 中没有编码任何数组大小。它知道的唯一大小是 X 的大小,这还不够。
希望它有意义,并解释了为什么不能使用 int** 而不是 x[][]。
也许这张图向您展示了两种多维数组声明之间的区别。 (有时人们不理解这一点。)
第一个说 a
是一个由 100 个连续的 7-int
块组成的块,或者总共 700 ints
个块,所有块都在一起。
第二个说 a
是一个指针数组,其中每个指针指向 ints
的不同块,分散在内存中。
编译器需要知道这一点,因为如果你写 a[i][j]
它必须生成完全不同的代码。
我有一个 class,里面有一个大的二维数组。它曾经是一个分配在堆上的动态数组,现在它是我更喜欢的静态大小。
private:
int fontTextureCoords_[100][7];
我必须将类型转换添加到访问器,以便 return 数组在 class 之外访问,目前工作正常,但我不确定它是否安全或者正确的处理方式。
public:
inline int **getFontTextureCoords()
{
return (int**)fontTextureCoords_;
}
这样做安全/正确吗?还是有更好的方法 return指向多维数组的指针?
将 int fontTextureCoords_[100][7];
之类的数组转换为 int**
是不正确的。它会导致未定义的行为。
如果不是太多,把getFontTextureCoords
改成:
inline int (*getFontTextureCoords()) [7]
{
return fontTextureCoords_;
}
并将其用作:
int (*ptr)[7] = getFontTextureCoords();
如果您可以选择使用std::vector
或std::array
,最好使用它们。
这不是正确的方法,不应编译。二维数组不能转换为指向指针的指针。您必须 return 一个指向数组的指针,使用 typedef 最容易编写:
using T = int[7];
inline T* getFontTextureCoords() { return fontTextureCoords_; }
尽管仅 return 引用整个数组会好得多:
using T = int[100][7];
inline T& getFontTextureCoords() { return fontTextureCoords_; }
你也可以 std::array<std::array<int, 7>, 100>
。
C/C++中没有多维数组。只有一维数组。你可以有一个一维数组,它的每个元素都是另一个一维数组。虽然看起来没有什么区别,但它是存在的,而且非常重要。
这正是传递逻辑不起作用的方式。每个人都经历过。 'If single-dimensional arrays are passed as a pointer to the first elelement, 2-D arrays should be passed as a pointer to pointer to first element, etc'。但由于它不是二维数组,而是数组的数组,所以无法应用该逻辑。
您可以通过以下方式进行推理。比方说,你有一个类型为 X 的数组。
X x[10];
如何访问第 5 个元素?简单 -
x[5] = 42;
但是编译器在看到它时会做什么?它大致是这样的:
*(&x[0] + 5) = 42;
所以它获取第一个元素的地址,并将其加 5 以获得第 5 个元素的地址。但是加 5 意味着什么呢?以字节为单位,应从数组开头的地址跳过多少字节才能到达请求的内存位置?当然是 5 * sizeof(X)。现在,如果你有“二维”数组,声明如下:
X x[2][3];
并且您尝试通过指向指针的指针来使用它:
px = (X**)x;
px[3][4] = 42;
记住,为了生成[][]的代码,编译器需要用*(px + )的方式表达。并且必须是数组的大小(因为数组的元素是数组)。但是为此您需要知道数组大小,正如您所见,您的 px 中没有编码任何数组大小。它知道的唯一大小是 X 的大小,这还不够。
希望它有意义,并解释了为什么不能使用 int** 而不是 x[][]。
也许这张图向您展示了两种多维数组声明之间的区别。 (有时人们不理解这一点。)
第一个说 a
是一个由 100 个连续的 7-int
块组成的块,或者总共 700 ints
个块,所有块都在一起。
第二个说 a
是一个指针数组,其中每个指针指向 ints
的不同块,分散在内存中。
编译器需要知道这一点,因为如果你写 a[i][j]
它必须生成完全不同的代码。