C++ 中的指针存储在哪里,在堆栈中还是在堆中?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24380935/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:43:24  来源:igfitidea点击:

Where are pointers in C++ stored, on the stack or in the heap?

c++pointersmemory-management

提问by nburk

I am trying to understand the difference between the stackand heapmemory, and this questionon SO as well as this explanationdid a pretty good job explaining the basics.

我试图了解堆栈内存之间的区别,SO 上的这个问题以及这个解释很好地解释了基础知识。

In the second explanation however, I came across an example to which I have a specific question, the example is this:

然而,在第二个解释中,我遇到了一个我有一个具体问题的例子,这个例子是这样的:

heap allocation example

堆分配示例

It is explained that the object mis allocated on the heap, I am just wondering if this is the full story. According to my understanding, the object itself indeed is allocated on the heapas the newkeyword has been used for its instantiation.

解释说对象m是在堆上分配的,我只是想知道这是否是完整的故事。根据我的理解,对象本身确实是在堆上分配的,因为new关键字已用于其实例化。

However, isn't it that the pointer to object mis on the same time allocated on the stack? Otherwise, how would the object itself, which of course is sitting in the heapbe accessed. I feel like for the sake of completeness, this should have been mentioned in this tutorial, leaving it out causes a bit of confusion to me, so I hope someone can clear this up and tell me that I am right with my understanding that this example should have basically two statements that would have to say:

但是,指向对象的指针m不是在同一时间分配在堆栈上吗?否则,如何访问当然位于堆中的对象本身。我觉得为了完整起见,本教程中应该提到这一点,将其省略会给我带来一些困惑,所以我希望有人能澄清这一点并告诉我我对这个示例的理解是正确的基本上应该有两个声明必须说:

1. a pointer to object mhas been allocated on the stack

1. 一个指向对象的指针m已经被分配到栈上

2. the object mitself (so the data that it carries, as well as access to its methods) has been allocated on the heap

2. 对象m本身(所以它携带的数据,以及对其方法的访问)已在堆上分配

采纳答案by Rakib

Your understanding may be correct, but the statements are wrong:

你的理解可能是正确的,但陈述是错误的:

A pointer to object mhas been allocated on the stack.

指向对象的指针m已在堆栈上分配。

mis thepointer. It is on the stack. Perhaps you meant pointer to a Memberobject.

m指针。它在堆栈上。也许你的意思是指向一个Member对象的指针

The object mitself (the data that it carries, as well as access to its methods) has been allocated on the heap.

对象m本身(它携带的数据以及对其方法的访问)已在堆上分配。

Correct would be to say the object pointed by mis created on the heap

正确的说法是指向的对象m是在堆上创建的

In general, any function/method local object and function parameters are created on the stack. Since mis a function localobject, it is on the stack, but the object pointed to by mis on the heap.

通常,任何函数/方法本地对象和函数参数都是在堆栈上创建的。因为m函数本地对象,所以在栈上,但是指向的对象m在堆上。

回答by M.M

"stack" and "heap" are general programming jargon. In particular , no storage is required to be managed internally via a stack or a heap data structure.

“堆栈”和“堆”是通用的编程术语。特别是,不需要通过堆栈或堆数据结构在内部管理存储。

C++ has the following storage classes

C++有以下存储类

  • static
  • automatic
  • dynamic
  • thread
  • 静止的
  • 自动的
  • 动态的
  • 线

Roughly, dynamiccorresponds to "heap", and automaticcorresponds to "stack".

粗略地说,动态对应“堆”,自动对应“堆栈”。

Moving onto your question: a pointer can be created in any of these four storage classes; and objects being pointed to can also be in any of these storage classes. Some examples:

继续你的问题:可以在这四个存储类中的任何一个中创建一个指针;被指向的对象也可以在任何这些存储类中。一些例子:

void func()
{
    int *p = new int;            // automatic pointer to dynamic object
    int q;                       // automatic object
    int *r = &q;                 // automatic pointer to automatic object
    static int *s = p;           // static pointer to dynamic object
    static int *s = r;           // static pointer to automatic object (bad idea)
    thread_local int **t = &s;   // thread pointer to static object 
}

Named variables declared with no specifier are automaticif within a function, or staticotherwise.

没有说明符声明的命名变量在函数内是自动的,否则是静态的

回答by user3553031

When you declare a variable in a function, it always goes on the stack. So your variable Member* mis created on the stack. Note that by itself, mis just a pointer; it doesn't point to anything. You can use it to point to an object on either the stack or heap, or to nothing at all.

当你在函数中声明一个变量时,它总是在栈上。所以你的变量Member* m是在堆栈上创建的。请注意,它本身m只是一个指针;它不指向任何东西。您可以使用它来指向堆栈或堆上的对象,或者根本不指向任何对象。

Declaring a variable in a class or struct is different -- those go where ever the class or struct is instantiated.

在类或结构中声明一个变量是不同的——那些在类或结构被实例化的地方。

To create something on the heap, you use newor std::malloc(or their variants). In your example, you create an object on the heap using newand assign its address to m. Objects on the heap need to be released to avoid memory leaks. If allocated using new, you need to use delete; if allocated using std::malloc, you need to use std::free. The better approach is usually to use a "smart pointer", which is an object that holds a pointer and has a destructor that releases it.

要在堆上创建一些东西,您可以使用newstd::malloc(或它们的变体)。在您的示例中,您使用在堆上创建一个对象new并将其地址分配给m。堆上的对象需要被释放以避免内存泄漏。如果分配 using new,则需要使用delete; 如果分配 using std::malloc,则需要使用std::free. 更好的方法通常是使用“智能指针”,它是一个持有指针并具有释放指针的析构函数的对象。

回答by Marco A.

Yes, the pointer is allocated on the stack but the object that pointer points to is allocated on the heap. You're correct.

是的,指针分配在堆栈上,但指针指向的对象分配在堆上。你是对的。

However, isn't it that the pointer to object m is on the same time allocated on the stack?

但是,指向对象m的指针不是在同一时间分配在栈上的吗?

I suppose you meant the Memberobject. The pointer is allocated on the stack and will last there for the entire duration of the function (or its scope). After that, the code might still work:

我想你的意思是Member对象。指针在堆栈上分配,并将在函数(或其作用域)的整个持续时间内持续存在。之后,代码可能仍然有效:

#include <iostream>
using namespace std;

struct Object {
    int somedata;
};

Object** globalPtrToPtr; // This is into another area called 
                         // "data segment", could be heap or stack

void function() {
    Object* pointerOnTheStack = new Object;
    globalPtrToPtr = &pointerOnTheStack;
    cout << "*globalPtrToPtr = " << *globalPtrToPtr << endl;
} // pointerOnTheStack is NO LONGER valid after the function exits

int main() {
     // This can give an access violation,
     // a different value after the pointer destruction
     // or even the same value as before, randomly - Undefined Behavior
    cout << "*globalPtrToPtr = " << *globalPtrToPtr << endl;
    return 0;
}

http://ideone.com/BwUVgm

http://ideone.com/BwUVgm

The above code stores the address of a pointer residing on the stack (and leaks memory too because it doesn't free Object's allocated memory with delete).

上面的代码存储了驻留在堆栈上的指针的地址(并且也会泄漏内存,因为它没有使用 释放Object分配的内存delete)。

Since after exiting the function the pointer is "destroyed" (i.e. its memory can be used for whatever pleases the program), you can no longer safely access it.

由于在退出函数后指针被“销毁”(即它的内存可以用于任何让程序满意的地方),您不能再安全地访问它

The above program can either: run properly, crash or give you a different result. Accessing freed or deallocated memory is called undefined behavior.

上面的程序可以:正常运行、崩溃或给你不同的结果。访问已释放或解除分配的内存称为未定义行为