在很多时候,需要存储的数据量到底有多大在事先往往是一个未知数,要想处理好这类情况,就需要在c++程序里使用动态内存。
动态内存支持程序员创建和使用种种能够根据具体需要扩大和缩小的数据结构,它们只受限于计算机的硬件内存总量和系统特殊约束。
1、静态内存
变量(包括指针变量)、固定长度的数组,某给定类的对象。我们可以在程序代码里通过它们的名字或者地址来访问和使用它们。而使用静态内存的最大弊端是,你不得不在编写程序时为有关变量分配一块尽可能大的内存(以防不够存放数据)。一旦程序开始运行,不管实际情况如何,那个变量都将占用那么多的内存,没有任何办法能改变静态内存的大小。
2、动态内存
动态内存由一些没有名字、只有地址的内存块构成,哪些内存块是在程序运行期间动态分配的。它们来自一个由标准c++库替你管理的内存池,从内存池申请一些内存需要用new语句,它将根据你提供的数据类型分配一块大小适当的内存。你不必担心内存块的尺寸问题,编译器能够记住分配每一种数据类型的单位长度并迅速计算出需要分配多少个字节。如果有足够的可用内存能满足你的申请,new语句将返回新分配地址块的起始地址。如果没有足够的可用内存空间,那么将会抛出std::bad_alloc异常。注意在用完内存块之后,应该用delete语句把它还给内存池。另外作为一种附加的保险措施,在释放了内存块之后还应该把与之关联的指针设置为NULL。
int *i = new int;
delete i;
为保险起见,应该把指针变量设置为NULL,i = NULL;
NULL指针的理解
有一个特殊的地址值叫做NULL指针,当把一个指针变量设置为NULL时,它的含义是那个指针将不再指向任何东西:
int *x;
x = NULL; // x这个时候啥都不指向
我们无法通过一个被设置为NULL的指针去访问数据。事实上,试图对一个NULL指针进行解引用将在运行时被检测到并将导致程序中止执行。所以在用delete释放内存后,指针会保留一个毫无意义的地址,我们要将指针变量赋值为NULL。
注意:
(1)静态内存这个术语与C++保留字static没有任何关系。静态内存意思是指内存块的长度在程序编译时被设定为一个固定的值,而这个值在程序运行时是无法改变的。
(2)new语句返回的内存块很可能充满“垃圾”数据,所以我们通常先往里边写一些东西覆盖,再访问它们,或者在类直接写一个构造器来初始化。
(3)在使用动态内存时,最重要的原则是每一条new语句都必须有一条与之匹配的delete语句,没有配对的delete语句或者有两个配对的delete语句都属于编程漏洞。尤其前者,将导致内存泄露。
例子:
#include
#include
using namespace std;
class Company //基类
{
public:
Company(string theName);
virtual void printInfo();
protected:
string name;
};
class TechCompany:public Company
{
public:
TechCompany(string theName, string product);
virtual void printInfo();
private:
string product;
};
Company::Company(string theName) //构造函数
{
name = theName;
}
void Company::printInfo()
{
cout << "这个公司的名字叫: " << name << ".\n";
}
TechCompany::TechCompany(string theName, string product):Company(theName)
{
this -> product = product;
}
void TechCompany::printInfo()
{
cout << name << "公司大量生产了" << product << "这款产品!\n";
}
int main()
{
Company *company = new Company("APPLE");
company -> printInfo();
delete company;
company = NULL;
company = new TechCompany("APPLE", "IPHONE");
company -> printInfo();
delete company;
company = NULL;
return 0;
}