我开始学习动态内存分配的主题。
我有以下代码:
#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() {
}
调试器的输出是:
Temporary breakpoint 6, main () at ../src/HeapStackTest02.cpp:18 18 A classAStack; Breakpoint 4, B::B (this=0x23aa58) at ../src/B.cpp:12 12 std::cout <<"Constructor B called" << std::endl; Breakpoint 5, A::A (this=0x23aa50) at ../src/A.cpp:13 13 std::cout <<"Constructor A called" << std::endl; Breakpoint 4, B::B (this=0x23aa40) at ../src/B.cpp:12 12 std::cout <<"Constructor B called" << std::endl; Breakpoint 4, B::B (this=0x60004b048) at ../src/B.cpp:12 12 std::cout <<"Constructor B called" << std::endl; Breakpoint 5, A::A (this=0x60004b040) at ../src/A.cpp:13 13 std::cout <<"Constructor A called" << std::endl; Breakpoint 1, main () at ../src/HeapStackTest02.cpp:30 30 return 0;
对于我的问题:
类A
的成员变量b
在哪里?
如果我查看第0x23a节中的地址,它似乎是堆栈,而第0x6000节似乎是堆。
我正在使用Windows 64位系统。
为什么成员变量b
也在堆上,而没有调用new
运算符?
考虑一下:
#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;
}
为了回答这个问题,让我们从找出我们有多少B类型的实例开始。答案是3。
一个实例是类型A的成员b(在堆栈上)。另一个是堆栈上B的实例,第三个是堆上A类型的成员B的实例。
为什么会堆起来?它就在那里,因为您在堆上创建了类型A的实例,而A的实例的成员是B的实例。
所以B的三个实例中有一个在堆上,另外两个在堆栈上。
成员是b
是您动态分配的对象的一部分,因此它是该动态分配的一部分,并且位于内存中的同一位置。
如果成员不是对象的一部分,会剩下什么?你会动态分配什么?
这就是为什么在看到new
时,应该避免使用术语“在堆上”。不仅仅是你新
的东西是“堆上的”。不,
new
动态分配一个对象以及该对象直接包含的所有内容。你如何写一个对象的声明和它是“在堆上”还是“在堆栈上”之间的任何心理联系都注定要失败。
确定物体存储时间的唯一可靠方法是了解其历史;确定对象存储位置的唯一可靠方法是不要麻烦,因为你不需要麻烦。
这应该是一个相对简单的问题,但它让我发疯。我正在尝试在JavaFX中创建扫雷器(主要用于练习),但我甚至无法显示一个简单的矩形。我以前运行过一次游戏,但我试图使游戏更加抽象,因此更容易编码,但我遇到了不显示任何问题。 我消除了所有无关的代码,使其尽可能简单。我基本上是在尝试创建一个名为Box的具有特定颜色和大小的矩形,将框添加到窗格中,并显示窗格。为了使Box成为可以在窗格上显示的节点,我使Box
我需要一个数据结构用于我的用例。我应该能够将项目推入数据结构,并且我只想从堆栈中检索最后一个项目。JavaDoc for Stack表示:
我是JProfiler的新手。我创建了一个非常简单的测试应用程序。这是一个带有main方法的Main.java: 注意,我暂停直到按键。通过这种方式,我确信主作用域在我按下一个键之前不会结束,所以我希望e存在并且不会被垃圾收集(如果这个假设不正确,请纠正我)。示例类: 我使用JProfiler Eclipse插件启动上述应用程序。我创建了一个基于完整仪器配置文件的会话;我已经删除了Java EE和
我有一个Camel-ReST路由,它使用Jackson将集合转换为JSON,但当集合中的对象包含LocalDate时,它会抛出一个错误(没有LocalDate,一切都很好)。 com.fasterxml.jackson.databind.exc.:默认不支持Java8日期/时间类型:添加模块"com.fasterxml.jackson.datatype: jackson-datatype-jsr3
日志输出为 日志输出为 为什么会这样?为什么不打印异常详细信息?我必须做什么才能获得堆栈跟踪信息? 日志框架:org.slf4j 1.7.26 logback 1.2.3
问题内容: 我的用例需要一个数据结构。我应该能够将项目推送到数据结构中,而我只想从堆栈中检索最后一个项目。该堆栈的JavaDoc说: Deque接口及其实现提供了一组更完整和一致的LIFO堆栈操作,应优先使用此类。例如: 我绝对不希望这里出现同步行为,因为我将使用方法本地的数据结构。除了这个,我为什么还要在这里呢? PS:Deque的Javadoc说: 双端队列也可以用作LIFO(后进先出)堆栈。