【问题标题】:the scope of a pointer?指针的范围?
【发布时间】:2011-02-26 14:32:26
【问题描述】:

好的,所以我确实发现了一些几乎相似的问题,但它们实际上让我对指针更加困惑。

C++ Pointer Objects vs. Non Pointer Objects

在上面的链接中,他们说如果你声明一个指针,它实际上保存在堆上而不是堆栈上,不管它是在哪里声明的。这是真的 ??还是我误会???我认为不管是指针还是非指针,如果它是一个全局变量,它的生命周期与应用程序一样长。如果它是一个局部变量或在循环或函数中声明,它的生命只与其中的代码一样长。

【问题讨论】:

    标签: c++ visual-studio visual-studio-2008 visual-c++


    【解决方案1】:

    看来您需要抓住the classic K&R C book 并通读第 4 章和第 5 章,以彻底了解声明和定义、变量范围和指针之间的区别。

    【讨论】:

      【解决方案2】:

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

      • 在堆栈上(作为函数或语句块中的本地 auto 变量)
      • 静态(作为全局变量或静态类成员)
      • 在堆上(作为new 对象或作为类对象成员)

      指针指向的对象(引用)同样可以分配在这三个地方。不过,一般来说,指向对象是使用new 运算符分配的。

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

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

      自动指针可以减轻对指向对象的管理工作。当指针超出范围时,通过auto_ptr 分配的对象将被删除。可以将对象从其拥有的auto_ptr 分配给另一个auto_ptr,从而将对象所有权转移到第二个指针。

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

      【讨论】:

      • +1。每个人都忘记了变量是在使用它们的地方定义的。如果它们是类的成员变量 - 它们可以与类的实例一起位于堆栈或堆上。
      【解决方案3】:
      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),那么它就在堆上。一般来说,您只能使用指针访问动态分配的内存。这可能是产生混乱的地方。

      【讨论】:

        【解决方案4】:

        我以为不管指针 或非指针,如果它是全局的 变量,它的寿命与 应用。如果它是一个局部变量 或在循环或函数中声明, 它的生命只和代码一样长 在里面。

        确实如此。

        他们说如果你声明一个指针 它实际上保存在堆上,并且 不在堆栈上

        那是错误的,部分。您可以在堆或堆栈上有一个指针。这取决于你在哪里以及如何声明它。

        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
        }
        

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

        【讨论】:

          【解决方案5】:

          需要区分指针(持有内存位置的变量)和指针指向的对象(指针持有的内存地址处的对象)。指针可以指向堆栈或堆上的对象。如果您使用 new 来分配对象,它将在堆上。同样,指针也可以存在于堆上。如果您在函数体中声明它,那么它将是一个局部变量并存在于本地存储中(即在堆栈上),而如果它是一个全局变量,它将存在于应用程序的数据部分中的某个位置。您还可以拥有指向指针的指针,并且类似地可以在堆上分配一个指针(并有一个指向该指针的指针)等等。请注意,虽然我已经引用了堆和堆栈,但 C++ 仅提到本地/自动存储和动态存储......它与实现无关。但实际上,local=stack 和 dynamic=heap。

          【讨论】:

          • 只是一个建议,您可以尝试将您的答案分成更少的文字墙段。 :)
          • @Amber,感谢您的建议。我会考虑的。
          【解决方案6】:
          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!
          

          希望对您有所帮助。

          【讨论】:

          • 是的,这是有道理的。这太疯狂了,我一直在阅读有关 C++ 的书籍,并阅读 Cplusplus 入门书。还有一些我如何设法错过指针的存储方式。他们概述了变量的范围,我有点认为指针是相同的方式。那么,如果堆栈上有 20 个整数而没有任何指向它怎么办。是否有可能找到它们并删除它们。或者在范围末尾删除它们是否至关重要
          • “如果堆栈上有 20 个 int 没有任何指向它怎么办。是否有可能找到它们并将它们删除。或者在范围末尾删除它们是否至关重要” ......您的意思是堆上的 20 个整数,如 Kornel 的示例 - 您必须“删除 []”它们。如果他会在堆栈上声明它们,那么不,不需要删除,因为没有使用 new (:
          • Google 获取有关堆栈内存的一些信息。一旦你明白了,你就不会感到困惑了。
          【解决方案7】:

          变量本身存储在堆栈或DATA段中,但它在使用new分配后指向的内存在堆内。

          【讨论】:

          • 好的,所以当您在本地范围内创建指针时。您在指向堆上的空间的堆栈上创建内存。在范围的末尾。栈上的内存被移除了,堆上的内存还在??
          • 正确。要摆脱堆空间,请使用delete
          • 那么使用delete很重要吗???或者是否有可能找到这些指针并在以后删除它们?
          • 智能指针是指一个指针,当它本身超出范围时,它会释放它所指向的堆空间。
          • @numerical25:一般来说,如果你自己打电话给new,那么你自己也可能需要打电话给delete
          猜你喜欢
          • 2019-05-09
          • 1970-01-01
          • 1970-01-01
          • 2021-09-17
          • 2018-10-07
          • 2011-07-22
          • 2015-09-30
          • 2016-11-15
          • 2013-06-17
          相关资源
          最近更新 更多