【问题标题】:The difference of dynamic memory, stack memory, and static memory and in c++?动态内存、栈内存、静态内存和c++的区别?
【发布时间】:2012-07-23 03:23:58
【问题描述】:

想知道C++中动态内存、栈内存和静态内存的区别。
以下是一些代码作为示例:

#include<iostream>
using namespace std;
char *GetMemory(void)
{
    char p[]="hello world";
    char *q="hello world"; 
    return q;
}
int main(void)
{
    return 0;
} 

为什么p在栈内存中,而q在动态内存中?

【问题讨论】:

  • 您在 C++ 中使用 new 关键字分配动态内存。 q 不是动态分配的。两个变量都在堆栈上。
  • 看看这个SO answer,看看堆和栈的区别。

标签: c++ memory


【解决方案1】:

pq 都是变量。 p 的类型为“12 个数组char”,q 的类型为“指向char 的指针”。 pq 都具有自动存储期限。也就是说,它们是在堆栈上分配的。

q 是一个指针,它被初始化为指向字符串"hello world" 的初始字符。此字符串是字符串文字,所有字符串文字都有静态存储持续时间。

p 是一个数组,所以当你用字符串字面量初始化p 时,它会导致p 声明一个字符数组,并且在初始化的时候,将字符串字面量的内容复制到大批。因此,当调用GetMemory() 时,会在堆栈上为数组p 分配空间,并将字符串文字"hello world" 的内容复制到该数组中。

您的代码不执行动态分配。


请注意,因为q 是指向具有静态存储持续时间的字符数组的指针,所以从函数返回q 是安全的:它指向的数组将在程序的整个持续时间内存在.但是,返回 p 并不安全,因为当函数返回时,p 将不复存在。

还要注意"hello world" 的类型是char const[12]。 C++ 中有一个不安全的隐式转换,它允许将字符串文字转换为指向字符串文字初始字符的char*。这是不安全的,因为它默默地放弃了 const 限定。在处理字符串文字时,您应该始终使用const char*,因为这些字符是不可修改的。 (在 C++ 语言的最新版本 C++11 中,这种不安全的转换已被删除。)

【讨论】:

    【解决方案2】:

    为什么栈内存是“p”,而动态内存是“q”?

    这不是真的; pq 都分配有自动存储持续时间(实现为堆栈结构)。它们之间的区别是:

    1. p 是一个数组,指向可修改的内存(堆栈分配)。
    2. q 是一个指针,指向已静态分配的只读内存。你真的应该把它声明为:

      const char *p = "随便";

    这里没有动态分配。您没有调用newmalloc 或一些使用幕后分配内存的例程。因此,从这个函数返回p是不正确的,因为一旦函数返回它就无效了。

    【讨论】:

    • 一点澄清:声明const char *p的目的是在我们尝试修改p指向的数据时产生编译器警告。没有这个,只有在程序运行时才会注意到修改只读内存的错误并得到段错误。
    【解决方案3】:

    对于您的示例,由于您使用的是字符串文字,因此很可能将其写入可执行文件的 DATA 段。没有分配动态内存。一个更好的例子是这样的:

    void foo()
    {
        //This is a stack variable. Space is allocated 
        //on the stack to store it. Its lifetime is
        //the routine that calls it.
    
        some_class stack_variable; 
    
        //This is a heap-allocated variable. It will
        //remain in memory indefinitely unless deleted.
        //If a pointer to this isn't returned, and it
        //isn't deleted by the end of the routine, this
        //will become a "memory leak".
    
        another_class *heap_variable = new another_class();
    
        //This is a (method) static variable. It retains its
        //value between method calls
    
        static int method_static = 1;
        ++method_static;
    
    } 
    

    在右大括号处,stack_variable 被清理(即它所占用的堆栈空间被回收)。 heap_variable 没有被删除,因此是内存泄漏。如果我们多次调用这个方法:

    for(int i = 0; i < 5; ++i) { foo(); }
    

    那么method_static的值为5。

    【讨论】:

      猜你喜欢
      • 2012-01-13
      • 2011-04-25
      • 2010-11-04
      • 2012-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多