二维 std::array 困境
2-Dimensional std::array woes
我认为我喜欢 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()
returns 4,符合预期,sum[0].size()
returns 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]
时,我希望会出现段错误,因为它是 运行!我现在愿意称自己为 hella confused。怎么回事?
额外信息:我正在使用设置了 -std=c++11 标志的 g++ 4.8.4。
第一个代码段不起作用,因为您访问的是随机内存位置。您(本质上)声明了一个(未初始化的)指针的二维数组,并且在您的代码中您正在取消引用它们,这是未定义的行为并且很可能导致段错误(您试图在随机内存位置上写入,这很可能是非映射到当前虚拟地址 space).
第二个片段很好;反转这两个索引是错误的,但您不会收到任何错误,因为 std::array
(或编译器对底层 C 数组)没有执行显式绑定检查。当你到达无效索引(第一个索引上的 4)时会发生什么在技术上仍然是未定义的行为;实际上,您可能会覆盖堆栈上不相关的变量,并且程序会继续运行。
// 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
的数组可能是正确的。
我认为我喜欢 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()
returns 4,符合预期,sum[0].size()
returns 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]
时,我希望会出现段错误,因为它是 运行!我现在愿意称自己为 hella confused。怎么回事?
额外信息:我正在使用设置了 -std=c++11 标志的 g++ 4.8.4。
第一个代码段不起作用,因为您访问的是随机内存位置。您(本质上)声明了一个(未初始化的)指针的二维数组,并且在您的代码中您正在取消引用它们,这是未定义的行为并且很可能导致段错误(您试图在随机内存位置上写入,这很可能是非映射到当前虚拟地址 space).
第二个片段很好;反转这两个索引是错误的,但您不会收到任何错误,因为 std::array
(或编译器对底层 C 数组)没有执行显式绑定检查。当你到达无效索引(第一个索引上的 4)时会发生什么在技术上仍然是未定义的行为;实际上,您可能会覆盖堆栈上不相关的变量,并且程序会继续运行。
// 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
的数组可能是正确的。