C++ 中的静态数组与动态数组

Posted

技术标签:

【中文标题】C++ 中的静态数组与动态数组【英文标题】:Static array vs. dynamic array in C++ 【发布时间】:2011-02-09 22:54:01 【问题描述】:

C++中静态数组和动态数组有什么区别?

我必须为我的班级做一个作业,它说不要使用静态数组,只能使用动态数组。我在书上和网上都看过,但我似乎不明白。

我认为静态是在编译时创建的,而动态是在运行时创建的,但我可能将其误认为是内存分配。

你能解释一下C++中静态数组和动态数组的区别吗?

【问题讨论】:

静态不是动态的反义词。要么你使用的书很糟糕,要么你断章取意。我将在下面添加一个新答案,希望能解决这个问题。 看这个问题的图:***.com/a/11698458/1143274 静态数组没有分配在栈或者堆上。 *固定数组 vs 动态数组 【参考方案1】:

静态数组

    静态数组在编译时分配内存。 大小是固定的。 位于堆栈内存空间中。 例如。 :整数数组[10]; //大小为10的数组

动态数组:

    内存在运行时分配。 大小不固定。 位于堆内存空间中。 例如。 : int* array = new int[10];

【讨论】:

【参考方案2】:

明确定义术语的含义很重要。不幸的是,静态和动态数组的含义似乎有多种定义。

Static variables 是使用static memory allocation 定义的变量。这是一个独立于 C/C++ 的通用概念。在 C/C++ 中,我们可以像这样创建具有全局、文件或局部范围的静态变量:

int x[10]; //static array with global scope
static int y[10]; //static array with file scope
foo() 
    static int z[10]; //static array with local scope

Automatic variables 通常使用stack-based memory allocation 实现。可以像这样在 C/C++ 中创建一个自动数组:

foo() 
    int w[10]; //automatic array

这些数组 x, y, zw 的共同点是它们每个的大小都是固定的,并且在编译时定义。

理解自动数组和静态数组的区别很重要的一个原因是静态存储通常在目标文件的data section(或BSS section)中实现,编译器可以使用访问数组的绝对地址,这在基于堆栈的存储中是不可能的。

dynamic array 通常的含义不是可调整大小的,而是使用dynamic memory allocation 实现的,在运行时确定固定大小。在 C++ 中,这是使用 new operator 完成的。

foo() 
   int *d = new int[n]; //dynamically allocated array with size n     

但可以使用alloca 创建一个在运行时定义的具有固定大小的自动数组:

foo() 
    int *s = (int*)alloca(n*sizeof(int))

对于真正的动态数组,应该使用 C++ 中的 std::vector 之类的东西(或 variable length array in C)。

OP 问题中的作业意味着什么?我认为很明显,想要的不是静态或自动数组,而是使用new 运算符使用动态内存分配或使用例如非固定大小数组的数组。 std::vector.

【讨论】:

【参考方案3】:

本地数组是在堆栈上创建的,并且具有自动存储持续时间——您不需要手动管理内存,但是当它们所在的函数结束时它们会被销毁。它们必须具有固定的大小:

int foo[10];

使用operator new[] 创建的数组具有动态存储持续时间并存储在堆上(技术上是“免费存储”)。它们可以有任何大小,但您需要自己分配和释放它们,因为它们不是堆栈帧的一部分:

int* foo = new int[10];
delete[] foo;

【讨论】:

这是正确的,但只是为了说明它是如何工作的。请不要在实际代码中执行此操作,而是使用 std::vector。 @Eddy:看情况是否需要向量 @Casebash:在哪种情况下您更喜欢数组? “你应该总是更喜欢使用向量或双端队列而不是数组。” - Herb Sutter(更出色的 C++) @EddyPronk 由于内存碎片的原因,人们可以使用固定数组作为一种池。并非每种情况都需要堆,使用基于堆栈的数组有特殊的好处。您将 std::vector 视为金锤,一种常见的反模式。 @EddyPronk:我很确定 Herb Sutter 指的是动态数组,例如 int* foo = new int[N],您必须自己使用 delete,因此在出现异常时要小心。静态数组不存在这些问题。【参考方案4】:

您可以有一个伪动态数组,其大小由用户在运行时设置,但之后固定。

int size;
cin >> size;
int dynamicArray[size];

【讨论】:

不是标准 C++ 的一部分(在 C99 中并作为 gcc 的编译器扩展)。【参考方案5】:

静态数组:效率。不需要动态分配或释放。

在 C、C++ 中声明的数组,包括 static 修饰符的函数是静态的。 示例:静态 int foo[5];

【讨论】:

@admdrew,这是真的,但这个问题从来没有得到很好的回答。最好的答案是 Joshua Clayton 的答案,但我认为更好的答案是 ***.com/questions/17775066/… @Zboson 很高兴知道,谢谢。呵呵,我才意识到我差不多一年前发表了这样的评论。【参考方案6】:

static 是 C 和 C++ 中的关键字,因此当应用于变量或数组时,static 不是一般的描述性术语,而是具有非常特定的含义。为了使混淆更加复杂,它在不同的上下文中具有三个不同的含义。因此,静态数组可以是固定的也可以是动态的。

让我解释一下:

第一个是 C++ 特定的:

静态类成员是未使用构造函数实例化或使用析构函数删除的值。这意味着必须以其他方式初始化和维护成员。静态成员可能是初始化为 null 的指针,然后在第一次调用构造函数时分配。 (是的,那将是静态和动态的)

两个继承自 C:

在函数中,静态变量是在函数调用之间保留其内存位置的变量。它是静态的,因为它只初始化一次并在函数调用之间保留其值(使用静态使函数不可重入,即不是线程安全的)

在函数外部声明的静态变量是全局变量,只能从同一个模块(包含任何其他#include 的源代码文件)内访问

您要问的问题(我认为)是动态数组与固定或编译时数组之间的区别。这是一个更简单的问题,编译时数组是预先确定的(在编译程序时)并且是函数堆栈框架的一部分。它们是在主函数运行之前分配的。动态数组在运行时使用“new”关键字(或 C 中的 malloc 系列)分配,并且它们的大小事先不知道。在程序停止运行之前,不会自动清理动态分配。

【讨论】:

+1,你的回答是最准确最准确的,应该得到更多的投票。 如果您使用new[] 运算符声明数组的大小,那么直到运行时才知道大小怎么办?即int* p = new int[10] "它们是在主函数运行之前分配的。"为什么要在进入相关块之前分配栈变量? 堆栈变量(通常是函数中的局部变量)在堆栈帧中具有预定义的大小和位置,并且在主函数运行之前分配整个堆栈,@AlwaysLearning。当通过函数调用进入堆栈帧时,堆栈指针被更新,但新的堆栈帧在堆栈内。没有更多的堆栈被分配。事实上,太大的变量(例如一个巨大的数组)或太多的函数调用同时打开会导致堆栈溢出,本网站就是为此而命名的。 @JoshuaClayton 我认为这不正确。当您不知道要输入多少次递归函数时,如何为递归函数分配堆栈帧(注意复数)?【参考方案7】:

是的,静态数组是在编译时创建的,而动态数组是在运行时创建的。至于它们的内存位置的差异,静态位于堆栈上,而动态则在堆上创建。位于堆上的所有内容都需要内存管理,除非存在 .net 框架中的垃圾收集器,否则存在内存泄漏的风险。

【讨论】:

【参考方案8】:

静态数组与数组中的元素相匹配

动态数组而不给出数组内部的元素

示例:

     char a[10]; //static array
       char a[];  //dynamic array

【讨论】:

我认为他说的没错。当你精确的数组长度时,它是一个静态数组,当你不给出长度时,它是一个动态数组。但由于他不知道如何写英文,这就是为什么人们会记下这个答案。【参考方案9】:

静态数组在编译时分配内存,内存分配在堆栈上。而动态数组在运行时分配内存,而内存是从堆中分配的。

int arr[] =  1, 3, 4 ; // static integer array.   
int* arr = new int[3]; // dynamic integer array.

【讨论】:

全局数组是一个静态数组,它是在数据段中实现的,而不是从堆栈中实现的。【参考方案10】:

我认为您的课程中使用的语义令人困惑。 “静态”可能意味着简单的“恒定大小”,而“动态”可能意味着“可变大小”。在这种情况下,一个恒定大小的数组可能如下所示:

int x[10];

而“动态”结构就是允许在运行时增加或减少底层存储的任何类型的结构。大多数时候,来自 C++ 标准库的 std::vector 类就足够了。像这样使用它:

std::vector<int> x(10); // this starts with 10 elements, but the vector can be resized.

std::vector 定义了operator[],因此您可以使用与数组相同的语义。

【讨论】:

我认为“动态数组”很明显,它们仅表示动态分配的数组(即可以在运行时动态指定大小的数组)。喜欢new int[10] @jalf:我更关心“静态”这个词。为了保持一致性,我更喜欢将“动态数组”称为已分配或可变大小的数组。 很好,因为静态数组可以是自动的并在堆栈上实现,也可以是全局的并在数据部分中实现。两者都是静态的,但在内部访问它们的代码可能非常不同。【参考方案11】:

我认为在这种情况下,这意味着它是静态的,因为它的大小是固定的。 使用 std::vector。它有一个 resize() 函数。

【讨论】:

以上是关于C++ 中的静态数组与动态数组的主要内容,如果未能解决你的问题,请参考以下文章

堆栈动态和堆栈动态数组

C ++静态数组,如动态数组[重复]

为啥大型静态数组会产生段错误而动态却不会? (C++)

C++ 静态和动态数组初始化

C++ 动态内存分配与结构中的数组

java的静态数组和动态数组有啥区别?