Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C/C++;静态阵列与动态阵列的性能比较_C++_C_Performance_Memory_Data Structures - Fatal编程技术网

C++ C/C++;静态阵列与动态阵列的性能比较

C++ C/C++;静态阵列与动态阵列的性能比较,c++,c,performance,memory,data-structures,C++,C,Performance,Memory,Data Structures,当性能对应用程序至关重要时,是否应该考虑是否在堆栈上声明数组而不是堆上声明数组?请允许我概述为什么会想到这个问题 由于C/C++中的数组不是对象,会衰减为指针,因此编译器使用提供的索引执行指针算法来访问元素。我的理解是,当经过第一维时,这个过程与静态声明的数组和动态声明的数组不同 如果我在堆栈上声明一个数组,如下所示 int array[2][3] = { 0, 1, 2, 3, 4, 5 } //In memory { row1 } { row2 } 此数组将以行主格式

当性能对应用程序至关重要时,是否应该考虑是否在堆栈上声明数组而不是堆上声明数组?请允许我概述为什么会想到这个问题

由于C/C++中的数组不是对象,会衰减为指针,因此编译器使用提供的索引执行指针算法来访问元素。我的理解是,当经过第一维时,这个过程与静态声明的数组和动态声明的数组不同

如果我在堆栈上声明一个数组,如下所示

  int array[2][3] = { 0, 1, 2, 3, 4, 5 }
  //In memory        { row1 } { row2 }
此数组将以行主格式存储在内存中,因为它存储在连续的内存块中。这意味着当我试图访问数组中的元素时,编译器必须执行一些加法和乘法,以确定正确的位置

所以如果我要做以下的事情

  int x = array[1][2]; // x = 5
int x = array[1][1];
然后,编译器将使用以下公式:

i=行索引j=列索引n=单行的大小(此处n=2)
数组=指向第一个元素的指针

  *(array + (i*n) + j)
  *(array + (1*2) + 2)  
这意味着,如果我在这个数组上循环以访问它的每个元素,那么每个索引访问都会执行一个额外的乘法步骤

现在,在堆上声明的数组中,范例不同,需要多阶段解决方案。注意:我也可以使用C++新操作符,但是我相信数据表示方式没有区别。
  int ** array;
  int rowSize = 2;
  // Create a 2 by 3 2d array on the heap
  array = malloc(2 * sizeof(int*));
  for (int i = 0; i < 2; i++) {
      array[i] = malloc(3 * sizeof(int));
  }

  // Populating the array
  int number = 0;
  for (int i = 0; i < 2; i++) {
      for (int j = 0l j < 3; j++) {
          array[i][j] = number++;
      }
  }
这意味着乘法不再涉及,对吗?如果我要做以下事情

  int x = array[1][2]; // x = 5
int x = array[1][1];
然后,这将在数组[1]上执行间接/指针算法以访问指向第二行的指针,然后再次执行此操作以访问第二个元素。我这样说对吗


现在有了一些背景,回到问题上来。如果我正在为一个需要高性能的应用程序编写代码,比如一个渲染帧需要0.016秒的游戏,那么我是否应该在堆栈上使用数组而不是堆上使用数组?现在我意识到使用malloc或新操作符需要一次性的成本,但是在数据集变大的某个时刻(就像Big O analysis),是否最好遍历动态数组以避免行主索引?

关于哪个选项提供更好的性能,那么答案在很大程度上取决于你的具体情况。要知道其中一种方法是否更好,或者它们是否大致相等,唯一的方法是测量应用程序的性能

其中的一些因素是:您执行此操作的频率、阵列/数据的实际大小、系统的内存量以及系统管理内存的能力

如果你能在这两种选择中做出选择,那一定意味着尺寸已经确定了。然后,您不需要您所说明的多重分配方案。可以对二维阵列执行单个动态分配。在C中:

int (*array)[COLUMNS];
array = malloc(ROWS * sizeof(*array));
在C++中:

std::vector<std::array<int, COLUMNS>> array(ROWS);
std::向量数组(行);

只要确定了
,就可以执行单个分配以获得二维阵列。如果两者都不明确,那么您实际上就没有选择使用静态数组的余地。

通常在内存消耗和速度之间存在权衡。根据经验,我看到在堆栈上创建数组比在堆上分配更快。随着阵列大小的增加,这一点变得更加明显

您总是可以减少内存消耗。例如,您可以使用short或char代替int等

随着数组大小的增加,特别是使用realloc时,可能会有更多的页面替换(上下)来保持项目的连续位置


你也应该考虑到在堆栈中存储的东西的大小有一个下限,因为堆的这个上限是高的,但是正如我告诉的,性能的代价。P> > P> C++中实现2维数组的常用方法 将它包装在一个类中,使用

std::vector
,然后 具有计算索引的类访问器。然而:

任何有关优化的问题只能由 即使如此,它们也只对编译器有效 您正在进行测量的机器上使用

如果你写:

int array[2][3] = { ... };
然后是这样的:

for ( int i = 0; i != 2; ++ i ) {
    for ( int j = 0; j != 3; ++ j ) {
        //  do something with array[i][j]...
    }
}
很难想象一个编译器实际上不会生成 大致如下:

for ( int* p = array, p != array + whatever; ++ p ) {
    //  do something with *p
}
这是最基本的优化之一,而且 已经至少30年了

如果按照建议动态分配,编译器将 无法应用此优化。即使是单身 访问:矩阵的局部性较差,需要更多内存 访问,因此性能可能会降低

如果你在C++中,你通常会写一个<代码>矩阵< /代码>类, 对内存使用

std::vector
,并计算 使用乘法显式索引。(改进的地方性) 将可能导致更好的性能,尽管 乘法)这可能会使 编译器进行上述优化,但如果 这是一个问题,您始终可以为提供专门的迭代器 处理这一特殊案件。你会得到更多 可读且更灵活的代码(例如,维度没有 这将适用于“普通”C(而不是C++)

首先,让我们澄清一些术语

“static”是C语言中的一个关键字,如果将它应用于函数中声明的变量,它将极大地改变变量的分配/访问方式

变量(包括数组)可能位于3个位置(关于C):

  • 堆栈:这些是没有
    静态的函数局部变量
  • 数据部分:空间