这是我在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);
但是我在执行此操作时遇到Segmentation错误。谁能帮助我弄清楚我做错了什么?
答案 0 :(得分:3)
int** a;
这只是给你一个对象。一个int**
对象。它根本不指向任何地方。没有int
要分配。当您开始分配int
时,就好像它们存在一样,您会得到未定义的行为。
此外,指向int**
s的“2d数组”的int
的内存布局是这样的:int**
指向数组{的第一个元素{1}} s,int*
s指向int*
s数组中的第一个元素。这个内存不是连续的,因为它需要间接跳转内存,即它不是单个内存块。你不能只使用int
写信给它。
如果您只想要一个memset
s的固定编译时大小的2D数组,请执行:
int
其中int a[N][M];
和N
是常量表达式。 连续存储,但我仍然不建议使用M
。
或使用标准容器,例如:
memset
如果您需要动态尺寸,请尝试:
std::array<std::array<int, M>, N> a;
或者,您可以坚持使用std::vector<std::vector<int>> a(M, std::vector<int>(N));
,并确保动态分配int**
和int*
:
int
但这太丑了!
答案 1 :(得分:3)
int** a;
只是指向int
的指针的声明。
“现在我正在使用for循环初始化上述内容”
您没有在for
循环中初始化它,您只是尝试将0
分配给不存在的元素,这会产生 未定义的行为< / EM> 即可。您需要为这些元素动态分配内存,或者甚至更好:使用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
对象被破坏,内存将自动清除)答案 2 :(得分:1)
对于int **
,您通常不会有一个连续的内存块。假设你正确使用它,你将有一个指针数组。然后,每个指针都将分别为其分配一个数组。
在这种情况下,您无法将循环转换为单个memset
(并且仍会获得定义的行为)。
答案 3 :(得分:0)
我认为问题在于没有为实际存储分配内存。变量 a 只是指针(另外没有初始化)。到了什么地方?
答案 4 :(得分:0)
你说你这样分配了它:
a = new int*[m];
for(int i =0; i<m ;i++) a[i] = new int[n];
就像Jerry Conffin所说 - 这不会给你一个连续的内存块。
每个新数组(new int[n]
)将分配在一个可能完全不同的位置,而memset仅适用于连续的块,因此您必须“手动”重置每个数组。
顺便说一句 - 我很确定你不会看到在循环中使用memset会有任何性能提升(我认为memset本身使用循环实现)。