C++入门(3)——使用new分配内存

3/8/2017来源:ASP.NET技巧人气:1317

指针和数字

指针不是整型,虽然计算机通常把地址当作整数处理。指针描述的是位置,对两个地址相乘并没有意义。因此,不能简单地将整数赋给指针

使用new来分配内存

对指针有一定了解之后,我们来看看它如何实现在程序运行时分配内存。前面我们将指针初始为变量地址只是为了描述指针的作用,而变量是在编译时分配的有名称的内存。指针真正的用处在于,在运行阶段分配未命名的内存来储存值。在C语言中,可以使用库函数malloc() 来分配内存,在C++中仍然可以这么做,但有更好的方法new

int *a = new int;

new int告诉程序,需要适合存储int的内存。new运算符根据类型来确定需要多少字节的内存。然后它找到这样的内存,并返回其地址,将地址赋给a,a是被声明指向int的指针,现在*a是存储在那里的值。我们来看一下具体应用

#include <iostream> int main() { using namespace std; int nights = 1001; int * pt = new int; // allocate space for an int *pt = 1001; // store a value there cout << "nights value = "; cout << nights << ":location = " << &nights << endl; cout << "int values = " << *pt << ": location = " << pt << endl; double * pd = new double; // allocate space for a double *pd = 100001.0; // store a double there cout << "double value = " << *pd << ":location = " << pd << endl; cout << "location of pointer pd: " << &pd << endl; cout << "size of pt = " << sizeof(pt); cout << ":size of *pt = " << sizeof(*pt) << endl; cout << "size of pd = " << sizeof(pd); cout << "size of *pd = " << sizeof(*pd) << endl; return 0; }

结果如下

nights value = 1001:location = 0x7ffdd5606704 int values = 1001: location = 0x1034c20 double value = 100001:location = 0x1035050 location of pointer pd: 0x7ffdd5606708 size of pt = 8:size of *pt = 4 size of pd = 8size of *pd = 8

从中可以看到,虽然变量night 和指针*pt 指向的变量值相同,但一个是编译时由系统分配的地址,另一个是我们通过 new 由系统分配的地址。而且我们发现,对于指针pd,我们还可以对它再求地址,就得到这个指针变量的地址。(可以理解为指针管理了一个变量的两个方面——地址和值,而指针自己也有在内存中的存储地址)

使用delete释放内存

当需要内存时,可以使用new来请求,这只是C++内存管理数据包中有魅力的一方面。另一方面是delete 运算符在使用完内存后将其释放给内存池(而不是其他语言的垃圾回收)

int *ps = new int; //allocate memory with new delete ps; // free memory with delete when done

这将释放ps指向的内存,但不会删除指针ps本身,例如可以将ps重新指向另一个新分配的内存块。一定要配对地使用newdelete ,否则将发生内存泄漏(memory leak)。也就是说,被分配的内存再也无法使用了。

使用new来创建动态数组

如果程序只需要一个值,则可能会声明一个简单变量,但对于大型数据(如数组,字符串和结构),应使用new。假如一个程序,它是否需要数组取决于运行时用户提供的信息。如果通过声明来创建数组,则在程序被编译时将为它分配内存空间。不管程序最终是否使用数组,数组都在那里,它浪费了内存。 下面来看一下使用new创建动态数组

int *arr = new int [10] // get a block of 10 ints delete [] arr; // 方括号代表释放整个数组

new运算符返回第一个元素的地址,在这个例子中,该地址被赋给指针arr。那么如何访问其中的元素呢?第一个元素不成问题,由于arr指向数组的第一个元素,还有9个元素,只需要把指针当作数组名使用就可以,arr[0] 是第一个元素,以此类推。(这里不需要*号)

#include <iostream> int main() { using namespace std; double *p3 = new double[3]; p3[0] = 0.2; // space for 3 doubles p3[1] = 0.5; // treat p3 like an Array name p3[2] = 0.8; cout << "p3[1] is " << p3[1] << ".\n"; p3 = p3 + 1; cout << "Now p3[0] is " << p3[0] << " and "; cout << "p3[1] is " << p3[1] << ".\n"; p3 = p3 - 1; // point back to beginning delete []p3; // free the memory return 0; }

我们看一下输出

p3[1] is 0.5. Now p3[0] is 0.5 and p3[1] is 0.8.

从中可以知道,指针p3 被当作数组名来使用,p3[0] 为第一个元素,依次类推。将p3加1导致它指向第二个元素而不是第一个,将它减1之后,指针指向原来的值,这样程序便可以给delete[]提供正确的地址。