首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >动态记忆与“普通”记忆的区别

动态记忆与“普通”记忆的区别
EN

Stack Overflow用户
提问于 2009-06-20 07:20:56
回答 5查看 3.4K关注 0票数 12

使用new运算符分配的内存与通过简单变量声明(如int var )分配的内存之间有哪些技术差异?c++有任何形式的自动内存管理吗?

特别是,我有几个问题。首先,对于动态内存,您必须声明一个指针来存储您使用的实际内存的地址,所以动态内存不需要更多的内存吗?我不明白为什么指针是必要的,除非您声明一个数组。

第二,如果我要做这样一个简单的功能:

int myfunc() { int x= 2;int y= 3;返回x+y;}

...And调用它时,函数分配的内存会在其存在范围结束后立即释放吗?动态记忆呢?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-06-20 09:00:37

注:这个答案太长了。我什么时候会把它剪下来的。同时,评论如果你能想到有用的编辑。

为了回答您的问题,我们首先需要定义两个内存区域,称为堆栈

堆叠

把堆栈想象成一堆盒子。每个框表示函数的执行。一开始,当main被调用时,地板上有一个盒子。您定义的任何局部变量都在该框中。

一个简单的例子

代码语言:javascript
复制
int main(int argc, char * argv[])
{
    int a = 3;
    int b = 4;
    return a + b;
}

在本例中,在地板上有一个带有变量argc (整数)、argv (指向char数组的指针)、a (整数)和b (整数)的框。

不止一个盒子

代码语言:javascript
复制
int main(int argc, char * argv[])
{
    int a = 3;
    int b = 4;
    return do_stuff(a, b);
}

int do_stuff(int a, int b)
{
    int c = a + b;
    c++;
    return c;
}

现在,在地板上有一个盒子(用于main),上面有argcargvab。在该框的顶部,还有另一个框(用于do_stuff),其中包含abc

这个例子说明了两个有趣的效果。

你可能知道,

  1. b是按值传递的.这就是为什么do_stuff.
  2. Notice的方框中有这些变量的副本,这些变量不需要freedelete,也不需要这些变量的任何内容。当函数返回时,该函数的框将被销毁。

箱溢出

代码语言:javascript
复制
    int main(int argc, char * argv[])
    {
        int a = 3;
        int b = 4;
        return do_stuff(a, b);
    }

    int do_stuff(int a, int b)
    {
        return do_stuff(a, b);
    }

在这里,您在地板上有一个盒子(用于main,和以前一样)。然后,您有一个带有ab的框(用于b)。然后,您有另一个框(用于do_stuff调用自身),同样带有ab。然后又是另一个。很快,就会有堆栈溢出。

堆栈摘要

把堆栈想象成一堆盒子。每个框表示正在执行的函数,该框包含在该函数中定义的局部变量。当函数返回时,该框将被销毁。

更多技术性的东西

  • 每一个“方框”被正式称为堆栈帧。
  • 有没有注意到您的变量是如何具有“随机”默认值的?当一个旧的堆栈帧被“破坏”时,它就不再相关了。它不会被归零或类似的东西。下次堆栈帧使用这部分内存时,您将在局部变量中看到一些旧堆栈帧。

这就是动态内存分配发挥作用的地方。

把这堆想象成一片永无止境的绿色记忆草地。调用mallocnew时,会在堆中分配一个内存块。您将获得一个访问此内存块的指针。

代码语言:javascript
复制
int main(int argc, char * argv[])
{
    int * a = new int;
    return *a;
}

这里,在堆上分配一个新整数的内存值。您将得到一个名为a的指针,该指针指向该内存。

  • a是局部变量,在main的"box"

中也是如此。

动态内存分配原理

当然,使用动态分配的内存似乎会在指针上浪费几个字节。但是,没有动态内存分配,有些事情(很容易)是做不到的。

返回数组

代码语言:javascript
复制
int main(int argc, char * argv[])
{
    int * intarray = create_array();
    return intarray[0];
}

int * create_array()
{
    int intarray[5];
    intarray[0] = 0;
    return intarray;
}

这里发生了什么?您可以在create_array中“返回一个数组”。实际上,您返回一个指针,它只指向包含数组的create_array“框”的部分。当create_array返回时会发生什么?它的盒子被破坏了,你可以期望你的数组在任何时候都会被破坏。

相反,使用动态分配的内存。

代码语言:javascript
复制
int main(int argc, char * argv[])
{
    int * intarray = create_array();
    int return_value = intarray[0];
    delete[] intarray;
    return return_value;
}

int * create_array()
{
    int * intarray = new int[5];
    intarray[0] = 0;
    return intarray;
}

因为函数返回不会修改堆,所以您宝贵的intarray将不受损害地转义。但是,请记住,在您完成之后,delete[]它。

票数 21
EN

Stack Overflow用户

发布于 2009-06-20 07:26:00

动态内存存在于堆上,而不是堆栈上。动态内存的生命周期是从分配时间到取消分配时间。对于局部变量,它们的生存期仅限于在其中定义的函数/块。

关于函数中内存使用的问题,在您的示例中,局部变量的内存将在函数的末尾释放。但是,如果使用new动态分配内存,则不会自动释放内存,您将负责显式地使用delete释放内存。

关于自动内存管理,C++标准库为此提供了auto_ptr。

票数 5
EN

Stack Overflow用户

发布于 2009-06-20 07:26:06

由"new“分配的内存将在堆上结束。

在函数中分配的内存驻留在函数中,函数放在堆栈上。

在这里阅读有关堆栈和堆分配的信息:http://www-ee.eng.hawaii.edu/~tep/EE160/Book/chap14/subsection2.1.1.8.html

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1021138

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档