2010-06-02 56 views
2

好吧,所以我确实发现了一些几乎相似的问题,但他们实际上让我更加困惑于指针。指针的作用域?

C++ Pointer Objects vs. Non Pointer Objects

在上面的链接,他们说,如果你声明指针它实际上是保存在堆中,而不是堆,不论在何地在宣布。这是真的 ??还是我误解?我认为,无论是指针还是非指针,如果它是一个全局变量,它就像应用程序一样长。如果它是一个局部变量或者在一个循环或者函数中声明的话,它的寿命只和它内部的代码一样长。

回答

9

变量本身存储在堆栈或数据段中,但分配给new后指向的内存位于堆内。

+2

好吧,所以当你在本地范围内创建一个指针。您在堆栈上创建指向堆空间的内存。在范围的末尾。堆栈上的内存被删除,堆上的内存仍然是? – numerical25 2010-06-02 00:11:54

+0

正确。为了摆脱堆空间,你使用'delete'。 – Amber 2010-06-02 00:12:37

+0

那么使用删除至关重要?或者是否有可能找到这些指针并在以后删除它们? – numerical25 2010-06-02 00:22:03

4
void main() 
{ 
    int* p;   // p is stored on stack 
    p = new int[20]; // 20 ints are stored on heap 
} 
// p no longer exists, but the 20 ints DO EXSIST! 

希望有所帮助。

+0

是的,这是有道理的。这很疯狂,我一直在阅读有关C++的书籍,并阅读Cplusplus入门书。还有一些我如何设法错过如何存储指针。他们对变量的范围进行了概述,我认为指针是一样的。那么如果你在堆栈上有20个int,没有任何指向它。是否有可能找到并删除它们。或者在范围末尾删除它们至关重要 – numerical25 2010-06-02 00:19:41

+1

“那么如果你在堆栈上有20个整数并没有指向它,那么如果找到它们并将其删除,或者删除它们是至关重要的在范围的最后“......你的意思是20个整数,就像Kornel的例子 - 你必须”删除[]“它们。如果他会在堆栈中声明它们,那么不需要删除,因为没有使用新的(:: – Poni 2010-06-02 00:24:06

+0

谷歌有关堆栈内存的一些信息。一旦你明白了,你不会感到困惑。 – Poni 2010-06-02 00:24:46

3

有必要区分指针(保存存储单元的变量)和指针指向的对象(指针所保存的存储器地址处的对象)。指针可以指向堆栈上或堆上的对象。如果您使用新的分配对象,它将在堆上。同样,指针也可以生活在堆上。如果你在函数体中声明它,那么它将是一个局部变量并且存在于本地存储器中(即在堆栈中),而如果它是一个全局变量,它将驻留在你的应用程序数据部分的某处。你也可以有指向指针的指针,同样可以在堆上分配一个指针(并且有一个指向指针的指针),等等。注意,虽然我引用了堆和堆,但是C++仅提到了本地/自动存储和动态存储......它没有与实现对话。但实际上,local = stack和dynamic = heap。

+0

只是一个建议,你可能会尝试将你的答案分解成更少的文本段。:) – Amber 2010-06-02 00:14:27

+0

@Amber,谢谢你的建议。我会接受劝告。 – 2010-06-02 01:45:27

0

我认为,无论指针 或非指针,如果它是一个全球性 变量,它只要 应用生活。如果它的一个局部变量 或在一个循环或函数内声明,它的使用寿命只与其中的代码 一样长。

确实如此。

他们说,如果你声明指针 它实际上是保存在堆和 不是在栈中

这是不对的,部分地。你可以在堆或栈上有一个指针。这是你申报的地点和方式的问题。

void main() 
{ 
    char c = 0x25; 
    char *p_stack = &c; // pointer on stack 

    StructWithPointer struct_stack; // stack 
    StructWithPointer *struct_heap = new StructWithPointer(); // heap, thus its pointer member "p" (see next line) is also on the heap. 
    struct_heap->p = &c; // pointer on heap points to a stack 
} 

......并且,编译器可能决定使用指针寄存器!

1
void func() 
{ 
    int x = 1; 
    int *p = &x; 
} 
// p goes out of scope, so does the memory it points to 

void func() 
{ 
    int *p = new int; 
} 
// p goes out of scope, the memory it points to DOES NOT 

void func() 
{ 
    int x = 1; 
    int **pp = new int*; 
    *pp = &x; 
} 
// pp goes out of scope, the pointer it points to does not, the memory it points to does 

等等。指针是一个包含内存位置的变量。像所有变量一样,它可以位于堆或栈上,具体取决于它是如何声明的。它的价值 - 内存位置 - 也可以存在于堆或堆栈中。

通常情况下,如果您静态分配一些东西,它就在堆栈中。如果你动态地分配一些东西(使用new或malloc),那么它就在堆上。一般而言,您只能使用指针访问动态分配的内存。这可能是混乱发生的地方。

1

指针是一个变量,包含内存中某个其他对象的地址。指针变量可以分配:

    栈上
  • (如在功能或语句块的局部auto变量)
  • 静态(作为全局变量或静态类成员)在堆上
  • (作为new对象或作为类对象成员)

指针指向的对象(引用)同样也可以分配到这三个位置。但一般来说,使用new运算符分配指向对象。

当程序流离开声明的块(或函数)时,局部变量超出范围,即它们在堆栈中的存在消失。同样,对象的成员变量在其父对象超出作用域或从堆中删除时消失。

如果指针超出范围或其父对象被删除,指针引用的对象仍然存在于内存中。因此,按照经验法则,任何分配给对象(news)的对象都拥有对象,并且在不再需要对象时也应该使用delete对象。

自动指针会将指向对象管理中的一些苦差事带走。当指针超出范围时,通过auto_ptr分配的对象将被删除。该对象可以从其拥有的auto_ptr指定给另一个auto_ptr,该对象将对象所有权转移给第二个指针。

参考文献本质上是变相的指针,但这是另一个讨论的话题。

+0

+1。每个人都忘记了变量被定义在何处。如果它们是一个类的成员变量 - 它们可以在堆栈中或者堆类中。 – 2010-06-02 03:33:42

0

看起来你需要抓住the classic K&R C book并仔细阅读第4章& 5,以便全面了解声明和定义,变量范围和指针之间的区别。