- 之前接触到的程序在完成任务时所使用的内存空间都是固定不变的。
- 这个固定不变的内存空间是在编写程序的时候就可以知道和确定(一般以变量的形式),这些程序在程序运行期间不会动态地增加或减少内存空间。
C++也支持动态管理
一、静态内存
- 静态内存就是我们此前一直在使用的东西:变量(包括指针变量)、固定长度的数组、某给定类的对象。我们可以在程序代码里通过它们的名字或者地址来访问和使用它们。
- 使用静态内存的最大弊端是,你不得不在编写程序时为有关变量分配一块尽可能大的内存(以防不够存放数据)。一旦程序开始运行,不管实际情况如何,那个变量都将占用那么多的内存,没有任何办法能改变静态内存的大小。
二、动态内存
- 动态内存由一些没有名字、只有地址的内存块构成,那些内存块是在程序运行期间动态分配的。
- 它们来自一个由标准 C++ 库替你管理的”大池子”(内存池)
- 从内存池申请一些内存需要用 new 语句,它将根据你提供的数据类型分配一块大小适当的内存。你不必担心内存块的尺寸问题,编译器能够记住每一种数据类型的单位长度并迅速计算出需要分配多少个字节。
- 如果有足够的可用内存能满足你的申请, new 语句将返回新分配地址块的起始地址。如果没有足够的可用内存空间?那么 new 语句将抛出 std::bad_alloc 异常!
注意:在用完内存块之后,应该用 delete 语句把它还给内存池。另外作为一种附加的保险措施,在释放了内存块之后还应该把与之关联的指针设置为 NULL。
int *i=new int;
delete i;
i=NULL;
三、NULL指针
有一个特殊的地址值叫做 NULL 指针。当把一个指针变量设置为 NULL 时,它的含义是那个指针将不再指向任何东西:
int *x;
x = NULL; // x 这时候啥都不指向
我们无法通过一个被设置为 NULL 的指针去访问数据。事实上,试图对一个 NULL 指针进行解引用的话将在运行时被检测到并将导致程序中止执行。
所以在用 delete 释放内存后,指针会保留一个毫无意义的地址,我们要将指针变量赋值为 NULL。
注意:
- 请注意,静态内存这个术语与 C++ 保留字 static 没有任何关系。静态内存意思是指内存块的长度在程序编译时被设定为一个固定的值,而这个值在程序运行时是无法改变的。
- new 语句返回的内存块很可能充满”垃圾”数据,所以我们通常先往里边写一些东西覆盖,再访问它们,或者在类直接写一个构造器来初始化。
- 在使用动态内存时,最重要的原则是每一条 new 语句都必须有一条与之配对的 delete 语句,没有配对的delete 语句或者有两个配对的 delete 语句都属于编程漏洞。(尤其前者,将导致内存泄漏)
四、为对象分配内存
为对象分配内存和为各种基本数据类型( int,char, float… )分配内存在做法上完全一样。
- 用 new 向内存池申请内存
- 用 delete 来释放内存
#include <iostream>
#include <string>
class Company
{
public:
Company(std::string theName);
virtual void printInfo();
protected:
std::string name;
};
class TechCompany : public Company
{
public:
TechCompany(std::string theName, std::string product);
virtual void printInfo();
private:
std::string product;
};
Company::Company(std::string theName)
{
name = theName;
}
void Company::printInfo()
{
std::cout << "这个公司的名字叫:" << name << "。\n";
}
TechCompany::TechCompany(std::string theName, std::string product) : Company(theName)
{
this->product = product;
}
void TechCompany::printInfo()
{
std::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;
}
注意:
- 在重新使用某个指针之前千万不要忘记调用 delete语句,如果不这样做,那个指针将得到一个新内存块的地址,而程序将永远也无法释放原先那个内存块,因为它的地址已经被覆盖掉了。
- 请记住, delete 语句只释放给定指针变量正指向的内存块,不影响这个指针。在执行 delete 语句之后,那个内存块被释放了,但指针变量还依然健在哦。所以请记住要把指针变量设置为NULL。
未完待续。。。