我有一个名为Node
的结构。
现在,我这样做:
Node* temp;
temp = new Node();
temp是指向Node的指针,Node本身是一种复杂的数据类型。
问题1:堆上的内存分配是否连续?
问题2:堆上的哪个内存块“临时”确切指向?它是结构节点中第一个数据成员的内存地址吗?
现在,我这样做:
delete temp;
问题3:这会释放内存。那么,temp现在指向垃圾值还是指向NULL?
答案 0 :(得分:3)
问题1:堆上的内存分配是否连续?
是的,给你一个连续的区块。它并不一定意味着两个连续的分配将为您提供连续的块。
问题2:堆上的哪个内存块确实存在' temp'准确指向?它是结构节点中第一个数据成员的内存地址吗?
不一定,取决于Node的定义方式以及平台和编译器的ABI。
问题3:这会释放内存。那么,temp现在指向垃圾值还是指向NULL?
是的,它一直指向同一个地址(现在是免费的,最终可能会被重新分配),你可以将它设置为NULL。
问题2。我们来试试吧:
1)普通结构
#include <iostream>
class A {
public:
int a;
};
int main() {
A *b=new A();
std::cout << std::hex << b << std::endl;
std::cout << std::hex << &(b->a) << std::endl;
}
和结果(用cygwin编译)
0x800102d0
0x800102d0
所以在这种情况下我们很好。
2)继承
#include <iostream>
class A {
public:
int a;
};
class B: public A {
public:
int b;
};
int main() {
B *b=new B();
std::cout << std::hex << b << std::endl;
std::cout << std::hex << &(b->b) << std::endl;
std::cout << std::hex << &(b->a) << std::endl;
}
结果:
0x800102d0
0x800102d4
0x800102d0
所以,B *不再是指向B&B的第一个元素的指针,而是指向A的第一个元素的指针。
3)虚拟课程
#include <iostream>
class A {
public:
virtual ~A() { }
int a;
};
class B: public A {
public:
int b;
};
int main() {
B *b=new B();
std::cout << std::hex << b << std::endl;
std::cout << std::hex << &(b->b) << std::endl;
std::cout << std::hex << &(b->a) << std::endl;
}
和结果
0x800102d0
0x800102d8
0x800102d4
现在指针既不指向A的第一个元素,也指向第一个元素 B的元素,但是控制结构。
答案 1 :(得分:2)
对象本身是从连续的内存中分配的。如果你的意思是从连续的new
分配的堆中的位置:没有办法知道。堆管理器可以随心所欲地执行任何操作。在我调查过的实现中,它们是连续从初始堆中剥离的,但是在一些delete
和free
调用之后,在几个算法之一中搜索空闲列表以寻找合适的块,包括“首先适合“,”最合适“,等等。
是的,指针通常是分配的类实例的最低地址元素。但对于派生类,虚拟对象等,情况并非总是如此。
是的,delete
释放对象,但指针指向已分配的空间。在delete
之后取消引用指针是“不好的”。如果有再次测试的可能性,最好在NULL
之后将指针设置为delete
。
删除临时; temp = NULL;