【问题标题】:C++ 2D array indexing with 1 parameter (Why does this work?)带有 1 个参数的 C++ 2D 数组索引(为什么会这样?)
【发布时间】:2014-12-23 02:31:36
【问题描述】:

所以我一直在为二维数组类重载运算符()。对于我正在做的随机测试,return 设置为array[0][index]。现在只传递列设置为 0 的索引(行)。如果索引小于行(那么我们在下一行),它仍然返回数据,就像我指定了列一样?

基本代码示例:

class myArr
{
private:
    float array[3][3];
public:
    myArr::myArr(float a1, float a2, ... ) { array[0][0] = a1; array[0][1] = a2; ... }
    // ^ the "..." just means, the same action till float a9/array[2][2] = a9;
    float& operator() (unsigned index) { return array[0][index]; }
    const float operator() (unsigned index) const { return array[0][index]; }
};

int main()
{
    myArr test(1, 2, 3, 4, 5, 6, 7, 8, 9);
    std::cout << myArr(4) << std::endl; // Displays 5
    myArr(4) = 0; // Set's element 4 to hold value 0
    return 0;
}

奇怪的是,这行得通。我可以使用 1 个参数设置/获取第 5 个元素。现在我想知道它为什么/如何工作,当然它应该出错“超出范围”或其他东西。最后,这会是“安全的”还是您强烈建议不要这样做?

我很少使用二维数组,主要是因为它们缺乏性能提升。

【问题讨论】:

    标签: c++ class operator-overloading multidimensional-array


    【解决方案1】:

    数组连续存储在内存中。在 C++ 中,多维数组在内存中逐行存储,所以我相信这是一个完全有效的内存,可以超出当前行进入下一行。如果超出二维数组的最后一行,就会发生越界。

    这是否是一件好事是一个不同的问题。显然,以这种方式编写代码会导致读者摸不着头脑,试图弄清楚您在做什么,因此您要避免以这种方式编写真正的代码。

    如果您要声明一个二维数组,那么您希望在数组的整个生命周期中都保留这些语义,因此我强烈建议您不要这样做。

    【讨论】:

    • @user3046336 在极端优化的情况下,执行 1D 访问可能比 2D 更快。除了那种情况,你避免它的结论是好的。
    • 它是否会导致未定义的行为像这样访问数组的末尾是有争议的(虽然我现在找不到相关的线程)
    【解决方案2】:

    当你分配一个二维数组时,它的内存是连续的。因此,如果您分配一个 3*3 的浮点数组,您将分配 9*4 个连续字节。 这导致:

    &array[0][i] = array + 0*3 + i = array + i = array[i]
    

    所以“偶然”,你会得到正确的结果。

    【讨论】:

    • 更具体地说,您分配了九个数组元素,在您的示例中每个元素占用四个字节,假设 sizeof(float) == 4。
    猜你喜欢
    • 2019-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多