3

这是我在 C++ 中的代码

int** a;
try{
  a = new int*[m];
  for(int i = 0; i<m;i++)
    a[i] = new int[n];
}

...现在我正在使用 for 循环初始化上述内容,如下所示:

for(int i = 0; i<m; i++)
  for(int j = 0; i<n; j++)
      a[i][j] = 0;

我正在努力提高性能,因此认为使用 memset 是个好主意。因此修改了我的代码以使用 memset 而不是 for 循环,如下所示:

memset(a, 0, sizeof(a[0][0]) * m * n);

但是我在执行这个时遇到了分段错误。谁能帮我弄清楚我做错了什么?

4

5 回答 5

4
int** a;

这只是给你一个对象。一个int**对象。它根本没有指向任何地方。没有int可分配的 s。当您开始分配给ints 时,就好像它们存在一样,您会得到未定义的行为。

此外,int**指向 s 的“二维数组”的内存布局int是这样的:int**指向 s 数组中的第一个元素int*,而int*s 指向 s 数组中的第一个元素int。该内存不是连续的,因为它需要间接跳转内存,即它不是单个内存块。您不能只使用memset.

如果您只想要一个固定的编译时大小的 2D 数组int,请执行以下操作:

int a[N][M];

whereNM是常量表达式。这连续存储的,但我仍然不建议使用memset.

或者使用标准容器,例如:

std::array<std::array<int, M>, N> a;

如果您需要动态大小,请尝试:

std::vector<std::vector<int>> a(M, std::vector<int>(N));

或者,您可以坚持使用int**并确保动态分配int*s 和ints:

int** a = new int*[M];
for (i = 0; i < N; i++) {
  a[i] = new int[N];
}

但这很丑!

于 2013-03-22T18:59:57.177 回答
3
int** a;

只是一个指向指针的声明int

“现在我正在使用 for 循环初始化上述内容”

您没有在for循环中对其进行初始化,您只是试图分配0给不存在的元素,这会产生未定义的行为。您需要为这些元素动态分配内存,或者甚至更好:std::vector改用:

std::vector< std::vector<int> > a(m, std::vector<int>(n, 0));

“我正在努力提高性能”

除非必要,否则不要这样做。不要过早优化。


编辑:在您提到您已经面临性能问题之后,您可以这样做:而不是这个二维 C 样式数组:

int** a = new int*[m];      // m = number of rows
for(int i = 0; i < m; i++)
    a[i] = new int[n];      // n = number of columns

你可以使用一维std::vector

std::vector<int> vec(rows * cols, 0);
...
vec[i * cols + j] = 7;   // equivalent of vec[i][j]
这将有更多的优势:
  • 您的二维数组将存储在连续的内存块中
  • 这块内存将立即分配,而不是许多小块
  • 由于空间局部性,元素的频繁访问将更快
    (“接近”的元素将在缓存内存中可用,因此您的
    程序不必从主内存加载它们)
  • 并且您将不负责内存管理(一旦对象被破坏
    ,内存将被自动清理)vector
于 2013-03-22T19:01:10.337 回答
1

使用 anint **通常不会有单个连续的内存块。假设您正确使用它,您将拥有一个指针数组。然后,这些指针中的每一个都将分别为其分配一个数组。

在这种情况下,您无法将循环转换为单个循环memset(并且仍然获得定义的行为)。

于 2013-03-22T19:00:11.027 回答
0

我认为问题在于未分配给实际存储的内存。变量a只是指针(此外未初始化)。它指向什么地方?

于 2013-03-22T19:00:15.833 回答
0

你说你是这样分配的:

a = new int*[m]; 
for(int i =0; i<m ;i++) a[i] = new int[n];

就像 Jerry Conffin 所说的那样——这不会给你一个单一的、连续的内存块。new int[n]每个新数组(通过循环使用 memset 的改进(memset 本身使用我认为使用循环实现)。

于 2013-03-22T19:08:14.547 回答