新建和删除工作如何工作以及存储在何处?

时间:2015-03-11 05:48:13

标签: c++

我有一个名为Node的结构。

现在,我这样做:

Node* temp;
temp = new Node();

temp是指向Node的指针,Node本身是一种复杂的数据类型。

  

问题1:堆上的内存分配是否连续?

     

问题2:堆上的哪个内存块“临时”确切指向?它是结构节点中第一个数据成员的内存地址吗?

现在,我这样做:

delete temp;
  

问题3:这会释放内存。那么,temp现在指向垃圾值还是指向NULL?

2 个答案:

答案 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)

  1. 对象本身是从连续的内存中分配的。如果你的意思是从连续的new分配的堆中的位置:没有办法知道。堆管理器可以随心所欲地执行任何操作。在我调查过的实现中,它们是连续从初始堆中剥离的,但是在一些deletefree调用之后,在几个算法之一中搜索空闲列表以寻找合适的块,包括“首先适合“,”最合适“,等等。

  2. 是的,指针通常是分配的类实例的最低地址元素。但对于派生类,虚拟对象等,情况并非总是如此。

  3. 是的,delete释放对象,但指针指向已分配的空间。在delete之后取消引用指针是“不好的”。如果有再次测试的可能性,最好在NULL之后将指针设置为delete

    删除临时; temp = NULL;