二维std :: array woes

时间:2015-09-16 21:51:25

标签: c++ arrays c++11 stl stdarray

我以为我喜欢C ++ 11中的std :: array的想法,但看起来它有一些夸克。我发现了这一点,因为以下代码给出了分段错误:

#include<array>
#include<iostream>

int main() {
        std::array<std::array<int*, 5>, 4> sum;

        //Initialize sum array
        std::cout << sum.size() << " " << sum[0].size() << "\n";
        for (size_t i = 0; i < sum.size(); i++) {
                for (size_t j = 0; j < sum[0].size(); j++) {
                        if (i == 0 || j == 0)
                                *(sum[i][j]) = 0;
                        else
                                sum[i][j] = nullptr;
                }
        }

    return 0;
}

输出:

4 5
Segmentation fault (core dumped)

sum.size()按预期返回4,sum[0].size()按预期返回5; IE似乎我们有一个包含4行和5列的数组。但是,当我尝试执行此程序时,我遇到了分段错误(如上所示)。 This link建议颠倒我访问数组的方式顺序(如更改sum[i][j]sum[j][i])应该有效,但我也会遇到段错误。这让我觉得我的指针可能做错了(我的C ++有点生疏),所以我将sum改为整数数组,所以它如下:

#include<array>
#include<iostream>

int main() {
        std::array<std::array<int, 5>, 4> sum;

        //Initialize sum array
        std::cout << sum.size() << " " << sum[0].size() << "\n";
        for (size_t i = 0; i < sum.size(); i++) {
                for (size_t j = 0; j < sum[0].size(); j++) {
                        if (i == 0 || j == 0)
                                sum[i][j] = 0; //works as sum[j][i] too!!!
                        else
                                sum[i][j] = 1;

        std::cout << sum[i][j];
                }
     std::cout << "\n";
        }

        std::cout << "here\n";
    return 0;
}

哪个有效,并且输出:

4 5
00000
01111
01111
01111
here

然而,我很困惑,因为如果我将sum[i][j]切换到sum[j][i],它也会起作用并输出同样的东西!当我第一次运行内循环的最后一次迭代时尝试sum[5][0]时,我希望得到一个seg-fault!我现在愿意把自己称为hella困惑。发生了什么事?

额外信息:我正在使用g ++ 4.8.4并设置-std = c ++ 11标志。

2 个答案:

答案 0 :(得分:2)

第一个代码段不起作用,因为您正在访问随机内存位置。你声明(基本上)一个二维(未初始化)指针的二维数组,并且在你的代码中你取消引用它们,这是未定义的行为并且很可能导致段错误(你试图在随机内存位置写入,这很可能是非映射在当前虚拟地址空间中。)

第二个片段很好;反转这两个索引是错误的,但是你没有得到任何错误,因为std::array(或底层C数组上的编译器)没有执行显式绑定检查。当你到达无​​效索引(第一个索引上的4)时发生的事情在技术上仍然是未定义的行为;实际上,你可能会覆盖堆栈中不相关的变量,程序会继续运行。

答案 1 :(得分:1)

// This is undefined behavior too
int* array[4][5];
*(array[0][0]) = 0;

// This is also undefined behavior, and for the same reason
int *cell;
*cell = 0;

如果要使用指针指向的对象,则必须使其指向实际对象;例如通过为其分配有效对象的地址,或创建一个全新的对象(例如,使用new)并将其分配给指针。

不知道你的最终目标,使用指针看起来像一个非常奇怪的设计选择;切换到int数组可能是正确的。