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


91

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

我必须为我的课程做一个分配,它说不要使用静态数组,而只能使用动态数组。我在书中和网上都看过,但我似乎不太明白。

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

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


1
静态与动态并非相反。您正在使用的书太糟糕了,或者您使它脱离上下文。我将在下面添加一个新答案,以期解决此问题。
约书亚·克莱顿

3
请参阅此问题中的图:stackoverflow.com/a/11698458/1143274静态数组未分配在堆栈或堆上。
Evgeni Sergeev 2013年

*固定阵列与动态阵列
csguy

Answers:


102

本地数组是在堆栈上创建的,并且具有自动存储期限-您不需要手动管理内存,但是当它们使用完函数时它们会被破坏。它们的大小一定是固定的:

int foo[10];

使用创建的数组operator new[]具有动态存储持续时间,并存储在堆中(从技术上讲是“免费存储”)。它们可以有任意大小,但是由于它们不属于堆栈框架,因此您需要自己分配和释放它们:

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

18
这是正确的,但仅是为了说明其工作原理。请不要在真实代码中执行此操作,而应使用std :: vector。
Eddy Pronk

23
@Eddy:这取决于是否需要向量的情况
Casebash 2010年

6
@Casebash:在哪种情况下,您希望使用数组?“您应该始终喜欢使用向量或双端队列,而不是使用数组。” -Herb Sutter(更出色的C ++)
Eddy Pronk

16
@EddyPronk出于内存碎片的原因,可以使用固定数组作为一种池。并非每种情况都需要堆,使用基于堆栈的数组有特殊的好处。您正在将std :: vector当作一把金锤子,这是一种常见的反模式。
void.pointer 2011年

4
@EddyPronk:我敢肯定,Herb Sutter意味着动态数组,就像int* foo = new int[N]delete自己需要的那样,因此在出现异常时要格外小心。静态数组没有这些问题。
亚历山大·马拉霍夫

31

static是C和C ++中的关键字,因此,static不是应用于一般的描述性术语,而是应用于变量或数组时具有非常特定的含义。更令人困惑的是,它在不同上下文中具有三种不同的含义。因此,静态数组可以是固定的,也可以是动态的。

让我解释:

首先是特定于C ++的:

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

有两个是从C继承的:

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

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

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


4
+1,您的答案是最准确,最准确的,应该会获得更多选票。
Z玻色子2014年

如果使用new[]运算符声明数组的大小,那么直到运行时才知道该大小?即int* p = new int[10]
wulfgarpro

“它们是在主要功能运行之前分配的。” 为什么要在进入相关块之前分配堆栈变量?
AlwaysLearning

堆栈变量(通常是函数中的局部变量)在堆栈框架内具有预定义的大小和位置,并且在主函数@AlwaysLearning运行之前分配了整个堆栈。通过函数调用输入堆栈帧时,将更新堆栈指针,但是新的堆栈帧位于堆栈内。不再分配任何堆栈。实际上,太大的变量(例如,巨大的数组)或太多的函数调用同时打开会导致堆栈溢出,为此站点命名。
约书亚·克莱顿

@JoshuaClayton我认为这是不正确的。当您不知道要输入多少次时,如何为递归函数分配堆栈帧(注意复数)?
AlwaysLearning

11

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

int x[10];

“动态”结构将是允许在运行时增加或减少基础存储的任何一种结构。大多数时候,std::vectorC ++标准库中的类就足够了。像这样使用它:

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

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


1
我认为,很明显,“动态数组”仅表示动态分配的数组(也就是说,可以在运行时动态指定大小的数组)。喜欢new int[10]
jalf 2010年

@jalf:我更关心“静态”一词。为了保持一致性,我更喜欢将“动态数组”称为已分配或可变大小的数组。
本·柯林斯

很好,因为静态数组可以是自动的,可以在堆栈上实现,也可以是全局的,可以在数据段中实现。两者都是静态的,但是在内部访问它们的代码可能非常不同。
Z玻色子2014年

9

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

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

4
全局数组是静态数组,它是在数据部分而不是从堆栈中实现的。
Z玻色子

8

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

静态变量是使用静态内存分配定义的变量。这是一个独立于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

通常使用基于堆栈的内存分配来实现自动变量。可以使用C / C ++创建自动数组,如下所示:

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

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

理解自动数组和静态数组之间的区别很重要的原因之一是,静态存储通常是在目标文件的数据部分(或BSS部分)中实现的,并且编译器可以使用绝对地址来访问数组这是基于堆栈的存储所无法实现的。

什么是通常由意味着动态数组没有一个是可调整大小的,但一个使用实现动态内存分配有一个固定的大小在运行时确定。在C ++中,这是使用newoperator来完成的。

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

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

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

对于真正的动态数组,应该使用std::vectorC ++中的某种东西(或C中的可变长度数组)。

OP的问题对任务意味着什么?我认为很明显,所需的不是静态或自动数组,而是使用new运算符使用动态内存分配或使用eg的非固定大小数组std::vector


3

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


2

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

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

不属于标准C ++(在C99中,并且作为gcc的编译器扩展)。
crashmstr 2014年

1

静态数组

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

动态数组:

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

0

是的,是的,静态数组是在编译时创建的,而动态数组是在运行时创建的。就它们的内存位置而言,最大的区别在于静态变量位于堆栈上,而动态变量位于堆上。除非存在垃圾收集器(如.net框架的情况),否则放置在堆上的所有内容都需要进行内存管理,否则存在内存泄漏的风险。


0

静态数组:效率。不需要动态分配或取消分配。

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


1
@admdrew,是的,但是这个问题从来没有得到很好的回答。最好的答案是约书亚·克莱顿的回答,但我认为一个更好的答案是这样的一个stackoverflow.com/questions/17775066/...
ž玻色子

@Zboson很高兴知道,谢谢。嘿,我刚刚意识到我差不多一年前就发表了这一评论。
admdrew

-3

静态arrary意味着在数组的侧面赋予元素

动态arrary意思是不放弃数组中的元素

例:

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

我认为他说的没错。当您要确定长度的精确数组时,它是一个静态数组;当您不给出长度时,它是一个动态数组。但是由于他不知道怎么写英语,这就是为什么人们在写下这个答案。
穆罕默德·泰亚卜(Mohammad tayyab),2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.