为啥我的对象似乎在堆上而不使用`new`?
Posted
技术标签:
【中文标题】为啥我的对象似乎在堆上而不使用`new`?【英文标题】: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
。这是一个真正的组合。
【参考方案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;
【讨论】:
以上是关于为啥我的对象似乎在堆上而不使用`new`?的主要内容,如果未能解决你的问题,请参考以下文章