【问题标题】:Why does my object appear to be on the heap without using `new`?为什么我的对象似乎在堆上而不使用`new`?
【发布时间】:2017-09-10 19:38:19
【问题描述】:

我开始学习动态内存分配的话题了。

我有以下代码:

#include <iostream>
#include "A.h"
#include "B.h"

using namespace std;

int main() {

   /* Both objects on Stack */

   A classAStack;
   B classBStack;

   /* Both objects on Heap*/
   //  A *classAHeap = new A();
   //  B *classBHeap = new B();

   /* A objects on Heap B ???*/
   A *classAHeap = new A();

   return 0;
}

#ifndef A_H_
#define A_H_

#include <iostream>
#include "B.h"

class A {
public:
   A();
   virtual ~A();

public:
   B b;
};

#endif /* A_H_ */

#include "A.h"

A::A() {
   std::cout <<"Constructor A called" << std::endl;
}

A::~A() {
}

#ifndef B_H_  
#define B_H_

#include <iostream>

class B {
public:
  B();
  virtual ~B();
};

#endif /* B_H_ */

#include "B.h"

B::B() {
  std::cout <<"Constructor B called" << std::endl;
}

B::~B() {
}

调试器的输出是:

临时断点6,main()在../src/HeapStackTest02.cpp:18 18 A类AStack; 断点 4,B::B (this=0x23aa58) at ../src/B.cpp:12 12 std::cout

我的问题:

A 类的成员变量 b 在哪里?

如果我查看 0x23a 部分的地址,它似乎是堆栈,而 0x6000 部分似乎是堆。

我正在使用 Windows 64 位系统。

为什么成员变量 b 也在堆上,而没有调用 new 运算符?

【问题讨论】:

  • 因为任何A 都包含B。这是一个真正的组合。

标签: c++ heap-memory dynamic-memory-allocation stack-memory


【解决方案1】:

成员 b 是您动态分配的对象的一部分,因此它是动态分配的一部分并且位于内存中的同一位置。

如果成员不是对象的一部分,会剩下什么?你会动态分配什么?

这就是为什么您在看到new 时应该避免使用“堆上”的术语。不仅仅是你new 的东西“在堆上”。不,new 动态分配一个对象以及该对象直接包含的所有内容。你如何编写一个对象的声明与它是“在堆上”还是“在堆栈上”之间的任何心理联系都注定要失败。

确定对象存储持续时间的唯一可靠方法是了解其历史;确定对象存储位置的唯一可靠方法是不要打扰,因为您不需要。

【讨论】:

    【解决方案2】:

    要回答这个问题,让我们从找出我们有多少个 B 类实例开始。 答案是 3。

    一个实例是类型 A 的成员 b(在堆栈上)。另一个是B在栈上的实例,第三个是A类型的成员b在堆上的实例。

    为什么它在堆上? 它在那里,因为您在堆上创建了类型 A 的实例,并且 A 的实例具有 B 的实例作为成员。

    所以 B 的 3 个实例之一在堆上,另外 2 个在堆栈上。

    【讨论】:

      【解决方案3】:

      考虑一下:

      #include <iostream>
      #include <string>
      
      class B {
      public:
          int64_t x = 42;
          int64_t y = 7;
      };
      
      class A1 {
      public:
          B b;
      };
      
      class A2 {
      public:
          A2() { b = new B(); }
          B* b;
          ~A2() { delete b; }
      };
      
      int main() {
          std::cout << sizeof(A1) << std::endl;   // prints 16
          std::cout << sizeof(A2) << std::endl;   // prints 8
      
          // Section (2)
          A1 a1;  // Instance of A1 and B are on the stack
          A2 a2;  // Instance of A2 is on the stack. B is on the heap.
      
          A1* a3 = new A1();
          std::cout << a3 == &(a3->b) << std:: endl;  // prints true
      
          A2* a4 = new A2();
          std::cout << a4 == a4->b << std::endl;  // prints false
      
          return 0;
      }   
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-27
        • 1970-01-01
        • 1970-01-01
        • 2013-03-05
        • 1970-01-01
        • 2012-10-19
        • 2013-04-11
        相关资源
        最近更新 更多