/*用指针p存储堆中的空间时,在将第二块内存空间赋给p之前,我们要释放p原来指向的内存空间, 这样才不会造成内存泄漏,不然的话p原来记录的内存空间就找不到了,而且也无法再次利用 注意:你在使用new以后,加入不再使用该块内存空间,那么一定要用delete来释放它*/ /*堆中可以保存变量,也可以保存对象,我们可以将对象保存在堆中,通过指针来访问它 */ /*创建对象的时候会自动调用类的构造函数来初始化对象的成员数据,也就是说会执行构造函数内的语句*/ #include <iostream> using namespace std; class Human { public: Human(){cout << "构造函数执行中……"; i = new int(999);} //把新开辟的堆的地址赋给Human的成员变量i,同时把999存进去 ~Human(){cout << "析构函数执行中……"; delete i;} //如果在对象中新开辟了一个堆,在析构函数中必须有delete i, 否则如果值向该类所在堆的指针被删除之后就找不到i了,从而造成内存泄漏,!!!!!!!!!!!!!!!但是一个在堆中创建的对象通过成员指针在创建新的空间用来保存数据没有什么意义,因为在堆中创建对象的时候已经为 它的所有数据成员提供了保存的空间 int get()const{return *i;} private: int *i; }; int main() { Human jack; cout << jack.get() << endl << endl; Human *p = new Human; cout << (*p).get() << endl << endl; cout << p->get() << endl << endl;//访问堆中对象的两种方法 1:p->get(); 2:(*p).get(); delete p; /*我们要删除在堆中创建的对象,我们可以直接删除指向该对象的指针,这样会自动调用对象的析构函数来销毁该对象,同时释放内存,在堆中创建的对象不用的时候记得删除,也就是delete p*/ return 0; }
对象在栈中有系统自动回收,对象在堆中由程序员手动释放,否则的话该对象占用的内存等到程序结束的时候才会被系统回收;
栈是一块连续的内存区域,它的大小是2M,也可能是1M,在不同的平台上它的大小不同
内存分配不同:
堆是不连续的内存区域,各块区域由链表将他们串联起来,这些串联起来的内存空间叫做堆
堆的上限是由系统中的有效虚拟内存来定的,因此获得的空间比较大,而且获得空间的方式也比较灵活
执行效率不同:
栈是由系统自动分配,因而执行效率较快,但是程序员不能对其进行操作
堆是由程序员分配的内存,一般速度比较慢,而且容易产生内存碎片,不过使用起来很方便
堆和栈各有优缺点,因此好多时候我们是将堆和栈结合使用的,比如我们在存储一些较大数据的时候,
我们将数据存放在堆中,却将指向该数据的指针存放在栈中,这样可以有效的提高程序的执行速度,
避免一些不该有的碎片,不过一般来说,假如不是特别大的数据,我们一般使用栈,比如函数调用过程中的参数,
返回地址,和局部变量都存放在栈中,这样可以大大加快程序的运行速度
堆中的数据,假设程序员不手动将其释放,它就会一直存放在堆中,程序结束时自动释放
栈中的数据只在函数内有效,超出函数就消失了,
全局变量只有在函数结束时候才会被释放,而且很容易被修改
堆中的每个内存单元都是匿名的,因此你必须在堆中申请一个内存单元地址,然后把它保存在一个指针中,
这样你只有使用该指针才能访问该内存单元的数据
在c++中使用关键字new来创建一个堆并分配内存,在new后面跟一个要分配的内存类型,
编译器根据这个类型来分配内存,比如int *p; p = new int;
由于计算机的内存地址是有限的,因此可能出现没有足够内存而无法满足new的请求,在这种情况下new会返回0
该值被赋给指针之后,该指针就是一个空指针,空指针不会指向任何有效数据,new除了返回空值之外,还会引发异常,
这时候需要进行异常情况处理,
下面代码演示如何创建一个堆并在不使用的时候释放堆中内存空间
/*假如你不需要一段内存空间,那就必须对指向他的指针关键字使用delete 当用delete释放一个指针指向的空间的时候可以将该指针清零,可以避免出错*/ #include <iostream> //qualify翻译为有资格,限制,取得资格 using namespace std; int main() { int *p = new int; delete p; //这将释放指针所指向的内存,而不会释放指针,因此你还可以使用该指针 p = 0; p = new int; *p = 8; cout << *p << endl; delete p; return 0; }